/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "gamePCH.h"
#include "Common.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Player.h"
#include "Unit.h"
#include "ObjectAccessor.h"
#include "Util.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "Battleground.h"
#include "OutdoorPvPMgr.h"
#include "Formulas.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "ScriptMgr.h"
#include "OutdoorPvPWG.h"

class Aura;
//
// EFFECT HANDLER NOTES
//
// in aura handler there should be check for modes:
// AURA_EFFECT_HANDLE_REAL set -  aura mod is just applied/removed on the target
// AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK set - aura is just applied/removed, or aura packet request is made
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK set - aura is recalculated or is just applied/removed - need to redo all things related to m_amount
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK - logical or of above conditions
// AURA_EFFECT_HANDLE_STAT - set when stats are reapplied
// such checks will speedup trinity change amount/send for client operations
// because for change amount operation packets will not be send
// aura effect handlers shouldn't contain any AuraEffect or Aura object modifications

pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] =
{
    &AuraEffect::HandleNULL,                        //  0 SPELL_AURA_NONE
    &AuraEffect::HandleBindSight,                   //  1 SPELL_AURA_BIND_SIGHT
    &AuraEffect::HandleModPossess,                  //  2 SPELL_AURA_MOD_POSSESS
    &AuraEffect::HandleNoImmediateEffect,           //  3 SPELL_AURA_PERIODIC_DAMAGE implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleAuraDummy,                   //  4 SPELL_AURA_DUMMY
    &AuraEffect::HandleModConfuse,                  //  5 SPELL_AURA_MOD_CONFUSE
    &AuraEffect::HandleModCharm,                    //  6 SPELL_AURA_MOD_CHARM
    &AuraEffect::HandleModFear,                     //  7 SPELL_AURA_MOD_FEAR
    &AuraEffect::HandleNoImmediateEffect,           //  8 SPELL_AURA_PERIODIC_HEAL implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleModAttackSpeed,              //  9 SPELL_AURA_MOD_ATTACKSPEED
    &AuraEffect::HandleModThreat,                   // 10 SPELL_AURA_MOD_THREAT
    &AuraEffect::HandleModTaunt,                    // 11 SPELL_AURA_MOD_TAUNT
    &AuraEffect::HandleAuraModStun,                 // 12 SPELL_AURA_MOD_STUN
    &AuraEffect::HandleModDamageDone,               // 13 SPELL_AURA_MOD_DAMAGE_DONE
    &AuraEffect::HandleNoImmediateEffect,           // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 15 SPELL_AURA_DAMAGE_SHIELD    implemented in Unit::DoAttackDamage
    &AuraEffect::HandleModStealth,                  // 16 SPELL_AURA_MOD_STEALTH
    &AuraEffect::HandleModStealthDetect,            // 17 SPELL_AURA_MOD_DETECT
    &AuraEffect::HandleModInvisibility,             // 18 SPELL_AURA_MOD_INVISIBILITY
    &AuraEffect::HandleModInvisibilityDetect,       // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
    &AuraEffect::HandleNoImmediateEffect,           // 20 SPELL_AURA_OBS_MOD_HEALTH implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNoImmediateEffect,           // 21 SPELL_AURA_OBS_MOD_POWER implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleAuraModResistance,           // 22 SPELL_AURA_MOD_RESISTANCE
    &AuraEffect::HandleNoImmediateEffect,           // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNoImmediateEffect,           // 24 SPELL_AURA_PERIODIC_ENERGIZE implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleAuraModPacify,               // 25 SPELL_AURA_MOD_PACIFY
    &AuraEffect::HandleAuraModRoot,                 // 26 SPELL_AURA_MOD_ROOT
    &AuraEffect::HandleAuraModSilence,              // 27 SPELL_AURA_MOD_SILENCE
    &AuraEffect::HandleNoImmediateEffect,           // 28 SPELL_AURA_REFLECT_SPELLS        implement in Unit::SpellHitResult
    &AuraEffect::HandleAuraModStat,                 // 29 SPELL_AURA_MOD_STAT
    &AuraEffect::HandleAuraModSkill,                // 30 SPELL_AURA_MOD_SKILL
    &AuraEffect::HandleAuraModIncreaseSpeed,        // 31 SPELL_AURA_MOD_INCREASE_SPEED
    &AuraEffect::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
    &AuraEffect::HandleAuraModDecreaseSpeed,        // 33 SPELL_AURA_MOD_DECREASE_SPEED
    &AuraEffect::HandleAuraModIncreaseHealth,       // 34 SPELL_AURA_MOD_INCREASE_HEALTH
    &AuraEffect::HandleAuraModIncreaseEnergy,       // 35 SPELL_AURA_MOD_INCREASE_ENERGY
    &AuraEffect::HandleAuraModShapeshift,           // 36 SPELL_AURA_MOD_SHAPESHIFT
    &AuraEffect::HandleAuraModEffectImmunity,       // 37 SPELL_AURA_EFFECT_IMMUNITY
    &AuraEffect::HandleAuraModStateImmunity,        // 38 SPELL_AURA_STATE_IMMUNITY
    &AuraEffect::HandleAuraModSchoolImmunity,       // 39 SPELL_AURA_SCHOOL_IMMUNITY
    &AuraEffect::HandleAuraModDmgImmunity,          // 40 SPELL_AURA_DAMAGE_IMMUNITY
    &AuraEffect::HandleAuraModDispelImmunity,       // 41 SPELL_AURA_DISPEL_IMMUNITY
    &AuraEffect::HandleNoImmediateEffect,           // 42 SPELL_AURA_PROC_TRIGGER_SPELL  implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
    &AuraEffect::HandleNoImmediateEffect,           // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
    &AuraEffect::HandleAuraTrackCreatures,          // 44 SPELL_AURA_TRACK_CREATURES
    &AuraEffect::HandleAuraTrackResources,          // 45 SPELL_AURA_TRACK_RESOURCES
    &AuraEffect::HandleNULL,                        // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a)
    &AuraEffect::HandleAuraModParryPercent,         // 47 SPELL_AURA_MOD_PARRY_PERCENT
    &AuraEffect::HandleNULL,                        // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect)
    &AuraEffect::HandleAuraModDodgePercent,         // 49 SPELL_AURA_MOD_DODGE_PERCENT
    &AuraEffect::HandleNoImmediateEffect,           // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus
    &AuraEffect::HandleAuraModBlockPercent,         // 51 SPELL_AURA_MOD_BLOCK_PERCENT
    &AuraEffect::HandleAuraModWeaponCritPercent,    // 52 SPELL_AURA_MOD_WEAPON_CRIT_PERCENT
    &AuraEffect::HandleNoImmediateEffect,           // 53 SPELL_AURA_PERIODIC_LEECH implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleModHitChance,                // 54 SPELL_AURA_MOD_HIT_CHANCE
    &AuraEffect::HandleModSpellHitChance,           // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
    &AuraEffect::HandleAuraTransform,               // 56 SPELL_AURA_TRANSFORM
    &AuraEffect::HandleModSpellCritChance,          // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
    &AuraEffect::HandleAuraModIncreaseSwimSpeed,    // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
    &AuraEffect::HandleNoImmediateEffect,           // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
    &AuraEffect::HandleAuraModPacifyAndSilence,     // 60 SPELL_AURA_MOD_PACIFY_SILENCE
    &AuraEffect::HandleAuraModScale,                // 61 SPELL_AURA_MOD_SCALE
    &AuraEffect::HandleNoImmediateEffect,           // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNULL,                        // 63 unused (3.2.0) old SPELL_AURA_PERIODIC_MANA_FUNNEL
    &AuraEffect::HandleNoImmediateEffect,           // 64 SPELL_AURA_PERIODIC_MANA_LEECH implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleModCastingSpeed,             // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
    &AuraEffect::HandleFeignDeath,                  // 66 SPELL_AURA_FEIGN_DEATH
    &AuraEffect::HandleAuraModDisarm,               // 67 SPELL_AURA_MOD_DISARM
    &AuraEffect::HandleAuraModStalked,              // 68 SPELL_AURA_MOD_STALKED
    &AuraEffect::HandleNoImmediateEffect,           // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
    &AuraEffect::HandleUnused,                      // 70 SPELL_AURA_EXTRA_ATTACKS clientside
    &AuraEffect::HandleModSpellCritChanceShool,     // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
    &AuraEffect::HandleModPowerCostPCT,             // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
    &AuraEffect::HandleModPowerCost,                // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
    &AuraEffect::HandleNoImmediateEffect,           // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL  implemented in Unit::SpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 75 SPELL_AURA_MOD_LANGUAGE
    &AuraEffect::HandleNoImmediateEffect,           // 76 SPELL_AURA_FAR_SIGHT
    &AuraEffect::HandleModMechanicImmunity,         // 77 SPELL_AURA_MECHANIC_IMMUNITY
    &AuraEffect::HandleAuraMounted,                 // 78 SPELL_AURA_MOUNTED
    &AuraEffect::HandleModDamagePercentDone,        // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
    &AuraEffect::HandleModPercentStat,              // 80 SPELL_AURA_MOD_PERCENT_STAT
    &AuraEffect::HandleNoImmediateEffect,           // 81 SPELL_AURA_SPLIT_DAMAGE_PCT implemented in Unit::CalcAbsorbResist
    &AuraEffect::HandleWaterBreathing,              // 82 SPELL_AURA_WATER_BREATHING
    &AuraEffect::HandleModBaseResistance,           // 83 SPELL_AURA_MOD_BASE_RESISTANCE
    &AuraEffect::HandleNoImmediateEffect,           // 84 SPELL_AURA_MOD_REGEN implemented in Player::RegenerateHealth
    &AuraEffect::HandleModPowerRegen,               // 85 SPELL_AURA_MOD_POWER_REGEN implemented in Player::Regenerate
    &AuraEffect::HandleChannelDeathItem,            // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
    &AuraEffect::HandleNoImmediateEffect,           // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth
    &AuraEffect::HandleNoImmediateEffect,           // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
    &AuraEffect::HandleNULL,                        // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE
    &AuraEffect::HandleNoImmediateEffect,           // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
    &AuraEffect::HandlePreventFleeing,              // 92 SPELL_AURA_PREVENTS_FLEEING
    &AuraEffect::HandleModUnattackable,             // 93 SPELL_AURA_MOD_UNATTACKABLE
    &AuraEffect::HandleNoImmediateEffect,           // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::Regenerate
    &AuraEffect::HandleAuraGhost,                   // 95 SPELL_AURA_GHOST
    &AuraEffect::HandleNoImmediateEffect,           // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget
    &AuraEffect::HandleNoImmediateEffect,           // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
    &AuraEffect::HandleAuraModSkill,                // 98 SPELL_AURA_MOD_SKILL_TALENT
    &AuraEffect::HandleAuraModAttackPower,          // 99 SPELL_AURA_MOD_ATTACK_POWER
    &AuraEffect::HandleUnused,                      // 100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell
    &AuraEffect::HandleModResistancePercent,        // 101 SPELL_AURA_MOD_RESISTANCE_PCT
    &AuraEffect::HandleNoImmediateEffect,           // 102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleAuraModTotalThreat,          // 103 SPELL_AURA_MOD_TOTAL_THREAT
    &AuraEffect::HandleAuraWaterWalk,               // 104 SPELL_AURA_WATER_WALK
    &AuraEffect::HandleAuraFeatherFall,             // 105 SPELL_AURA_FEATHER_FALL
    &AuraEffect::HandleAuraHover,                   // 106 SPELL_AURA_HOVER
    &AuraEffect::HandleNoImmediateEffect,           // 107 SPELL_AURA_ADD_FLAT_MODIFIER implemented in AuraEffect::CalculateSpellMod()
    &AuraEffect::HandleNoImmediateEffect,           // 108 SPELL_AURA_ADD_PCT_MODIFIER implemented in AuraEffect::CalculateSpellMod()
    &AuraEffect::HandleNoImmediateEffect,           // 109 SPELL_AURA_ADD_TARGET_TRIGGER
    &AuraEffect::HandleModPowerRegenPCT,            // 110 SPELL_AURA_MOD_POWER_REGEN_PERCENT implemented in Player::Regenerate, Creature::Regenerate
    &AuraEffect::HandleNoImmediateEffect,           // 111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget
    &AuraEffect::HandleNoImmediateEffect,           // 112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
    &AuraEffect::HandleNoImmediateEffect,           // 113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 115 SPELL_AURA_MOD_HEALING                 implemented in Unit::SpellBaseHealingBonusForVictim
    &AuraEffect::HandleNoImmediateEffect,           // 116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
    &AuraEffect::HandleNoImmediateEffect,           // 117 SPELL_AURA_MOD_MECHANIC_RESISTANCE     implemented in Unit::MagicSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 118 SPELL_AURA_MOD_HEALING_PCT             implemented in Unit::SpellHealingBonus
    &AuraEffect::HandleNULL,                        // 119 unused (3.2.0) old SPELL_AURA_SHARE_PET_TRACKING
    &AuraEffect::HandleAuraUntrackable,             // 120 SPELL_AURA_UNTRACKABLE
    &AuraEffect::HandleAuraEmpathy,                 // 121 SPELL_AURA_EMPATHY
    &AuraEffect::HandleModOffhandDamagePercent,     // 122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
    &AuraEffect::HandleModTargetResistance,         // 123 SPELL_AURA_MOD_TARGET_RESISTANCE
    &AuraEffect::HandleAuraModRangedAttackPower,    // 124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
    &AuraEffect::HandleNoImmediateEffect,           // 125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleModPossessPet,               // 128 SPELL_AURA_MOD_POSSESS_PET
    &AuraEffect::HandleAuraModIncreaseSpeed,        // 129 SPELL_AURA_MOD_SPEED_ALWAYS
    &AuraEffect::HandleAuraModIncreaseMountedSpeed, // 130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
    &AuraEffect::HandleNoImmediateEffect,           // 131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleAuraModIncreaseEnergyPercent,// 132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
    &AuraEffect::HandleAuraModIncreaseHealthPercent,// 133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
    &AuraEffect::HandleAuraModRegenInterrupt,       // 134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
    &AuraEffect::HandleModHealingDone,              // 135 SPELL_AURA_MOD_HEALING_DONE
    &AuraEffect::HandleNoImmediateEffect,           // 136 SPELL_AURA_MOD_HEALING_DONE_PERCENT   implemented in Unit::SpellHealingBonus
    &AuraEffect::HandleModTotalPercentStat,         // 137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
    &AuraEffect::HandleModMeleeSpeedPct,            // 138 SPELL_AURA_MOD_MELEE_HASTE
    &AuraEffect::HandleForceReaction,               // 139 SPELL_AURA_FORCE_REACTION
    &AuraEffect::HandleAuraModRangedHaste,          // 140 SPELL_AURA_MOD_RANGED_HASTE
    &AuraEffect::HandleRangedAmmoHaste,             // 141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
    &AuraEffect::HandleAuraModBaseResistancePCT,    // 142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
    &AuraEffect::HandleAuraModResistanceExclusive,  // 143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
    &AuraEffect::HandleNoImmediateEffect,           // 144 SPELL_AURA_SAFE_FALL                         implemented in WorldSession::HandleMovementOpcodes
    &AuraEffect::HandleAuraModPetTalentsPoints,     // 145 SPELL_AURA_MOD_PET_TALENT_POINTS
    &AuraEffect::HandleNoImmediateEffect,           // 146 SPELL_AURA_ALLOW_TAME_PET_TYPE
    &AuraEffect::HandleModStateImmunityMask,        // 147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
    &AuraEffect::HandleAuraRetainComboPoints,       // 148 SPELL_AURA_RETAIN_COMBO_POINTS
    &AuraEffect::HandleNoImmediateEffect,           // 149 SPELL_AURA_REDUCE_PUSHBACK
    &AuraEffect::HandleShieldBlockValue,            // 150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
    &AuraEffect::HandleAuraTrackStealthed,          // 151 SPELL_AURA_TRACK_STEALTHED
    &AuraEffect::HandleNoImmediateEffect,           // 152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
    &AuraEffect::HandleNoImmediateEffect,           // 153 SPELL_AURA_SPLIT_DAMAGE_FLAT
    &AuraEffect::HandleModStealthLevel,             // 154 SPELL_AURA_MOD_STEALTH_LEVEL
    &AuraEffect::HandleNoImmediateEffect,           // 155 SPELL_AURA_MOD_WATER_BREATHING
    &AuraEffect::HandleNoImmediateEffect,           // 156 SPELL_AURA_MOD_REPUTATION_GAIN
    &AuraEffect::HandleNULL,                        // 157 SPELL_AURA_PET_DAMAGE_MULTI
    &AuraEffect::HandleShieldBlockValue,            // 158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
    &AuraEffect::HandleNoImmediateEffect,           // 159 SPELL_AURA_NO_PVP_CREDIT      only for Honorless Target spell
    &AuraEffect::HandleNoImmediateEffect,           // 160 SPELL_AURA_MOD_AOE_AVOIDANCE                 implemented in Unit::MagicSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
    &AuraEffect::HandleNoImmediateEffect,           // 162 SPELL_AURA_POWER_BURN implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNoImmediateEffect,           // 163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
    &AuraEffect::HandleUnused,                      // 164 unused (3.2.0), only one test spell
    &AuraEffect::HandleNoImmediateEffect,           // 165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
    &AuraEffect::HandleAuraModAttackPowerPercent,   // 166 SPELL_AURA_MOD_ATTACK_POWER_PCT
    &AuraEffect::HandleAuraModRangedAttackPowerPercent,// 167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
    &AuraEffect::HandleNoImmediateEffect,           // 168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS  implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
    &AuraEffect::HandleNULL,                        // 170 SPELL_AURA_DETECT_AMORE       various spells that change visual of units for aura target (clientside?)
    &AuraEffect::HandleAuraModIncreaseSpeed,        // 171 SPELL_AURA_MOD_SPEED_NOT_STACK
    &AuraEffect::HandleAuraModIncreaseMountedSpeed, // 172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
    &AuraEffect::HandleNULL,                        // 173 unused (3.2.0) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS  only for Proclaim Champion spell
    &AuraEffect::HandleModSpellDamagePercentFromStat,// 174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT  implemented in Unit::SpellBaseDamageBonus
    &AuraEffect::HandleModSpellHealingPercentFromStat,// 175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
    &AuraEffect::HandleSpiritOfRedemption,          // 176 SPELL_AURA_SPIRIT_OF_REDEMPTION   only for Spirit of Redemption spell, die at aura end
    &AuraEffect::HandleCharmConvert,                // 177 SPELL_AURA_AOE_CHARM
    &AuraEffect::HandleNoImmediateEffect,           // 178 SPELL_AURA_MOD_DEBUFF_RESISTANCE          implemented in Unit::MagicSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
    &AuraEffect::HandleNoImmediateEffect,           // 180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS   implemented in Unit::SpellDamageBonus
    &AuraEffect::HandleNULL,                        // 181 unused (3.2.0) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
    &AuraEffect::HandleAuraModResistenceOfStatPercent,// 182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
    &AuraEffect::HandleNULL,                        // 183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school
    &AuraEffect::HandleNoImmediateEffect,           // 184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE  implemented in Unit::RollMeleeOutcomeAgainst
    &AuraEffect::HandleNoImmediateEffect,           // 185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
    &AuraEffect::HandleNoImmediateEffect,           // 186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE  implemented in Unit::MagicSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE  implemented in Unit::GetUnitCriticalChance
    &AuraEffect::HandleNoImmediateEffect,           // 188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
    &AuraEffect::HandleModRating,                   // 189 SPELL_AURA_MOD_RATING
    &AuraEffect::HandleNoImmediateEffect,           // 190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN     implemented in Player::CalculateReputationGain
    &AuraEffect::HandleAuraModUseNormalSpeed,       // 191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
    &AuraEffect::HandleModMeleeRangedSpeedPct,      // 192 SPELL_AURA_MOD_MELEE_RANGED_HASTE
    &AuraEffect::HandleModCombatSpeedPct,           // 193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
    &AuraEffect::HandleNoImmediateEffect,           // 194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
    &AuraEffect::HandleNoImmediateEffect,           // 195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
    &AuraEffect::HandleNULL,                        // 196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns
    &AuraEffect::HandleNoImmediateEffect,           // 197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
    &AuraEffect::HandleNULL,                        // 198 unused (3.2.0) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
    &AuraEffect::HandleNoImmediateEffect,           // 199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT  implemented in Unit::MagicSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill
    &AuraEffect::HandleAuraAllowFlight,             // 201 SPELL_AURA_FLY                             this aura enable flight mode...
    &AuraEffect::HandleNoImmediateEffect,           // 202 SPELL_AURA_CANNOT_BE_DODGED                implemented in Unit::RollPhysicalOutcomeAgainst
    &AuraEffect::HandleNoImmediateEffect,           // 203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE  implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
    &AuraEffect::HandleNoImmediateEffect,           // 204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
    &AuraEffect::HandleNULL,                        // 205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS
    &AuraEffect::HandleAuraModIncreaseFlightSpeed,  // 211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
    &AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent,// 212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
    &AuraEffect::HandleNoImmediateEffect,           // 213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
    &AuraEffect::HandleNULL,                        // 214 Tamed Pet Passive
    &AuraEffect::HandleArenaPreparation,            // 215 SPELL_AURA_ARENA_PREPARATION
    &AuraEffect::HandleModCastingSpeed,             // 216 SPELL_AURA_HASTE_SPELLS
    &AuraEffect::HandleNULL,                        // 217 69106 - killing spree helper - unknown use
    &AuraEffect::HandleAuraModRangedHaste,          // 218 SPELL_AURA_HASTE_RANGED
    &AuraEffect::HandleModManaRegen,                // 219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
    &AuraEffect::HandleModRatingFromStat,           // 220 SPELL_AURA_MOD_RATING_FROM_STAT
    &AuraEffect::HandleNULL,                        // 221 SPELL_AURA_MOD_DETAUNT
    &AuraEffect::HandleUnused,                      // 222 unused (3.2.0) only for spell 44586 that not used in real spell cast
    &AuraEffect::HandleNoImmediateEffect,           // 223 SPELL_AURA_RAID_PROC_FROM_CHARGE
    &AuraEffect::HandleUnused,                      // 224 unused (3.0.8a)
    &AuraEffect::HandleNoImmediateEffect,           // 225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
    &AuraEffect::HandleNoImmediateEffect,           // 226 SPELL_AURA_PERIODIC_DUMMY implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNoImmediateEffect,           // 227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE implemented in AuraEffect::PeriodicTick
    &AuraEffect::HandleNoImmediateEffect,           // 228 SPELL_AURA_DETECT_STEALTH stealth detection
    &AuraEffect::HandleNoImmediateEffect,           // 229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
    &AuraEffect::HandleAuraModIncreaseHealth,       // 230 SPELL_AURA_MOD_INCREASE_HEALTH_2
    &AuraEffect::HandleNoImmediateEffect,           // 231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
    &AuraEffect::HandleNoImmediateEffect,           // 232 SPELL_AURA_MECHANIC_DURATION_MOD           implement in Unit::CalculateSpellDuration
    &AuraEffect::HandleUnused,                      // 233 set model id to the one of the creature with id GetMiscValue() - clientside
    &AuraEffect::HandleNoImmediateEffect,           // 234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
    &AuraEffect::HandleNoImmediateEffect,           // 235 SPELL_AURA_MOD_DISPEL_RESIST               implement in Unit::MagicSpellHitResult
    &AuraEffect::HandleAuraControlVehicle,          // 236 SPELL_AURA_CONTROL_VEHICLE
    &AuraEffect::HandleModSpellDamagePercentFromAttackPower,// 237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER  implemented in Unit::SpellBaseDamageBonus
    &AuraEffect::HandleModSpellHealingPercentFromAttackPower,// 238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
    &AuraEffect::HandleAuraModScale,                // 239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
    &AuraEffect::HandleAuraModExpertise,            // 240 SPELL_AURA_MOD_EXPERTISE
    &AuraEffect::HandleForceMoveForward,            // 241 SPELL_AURA_FORCE_MOVE_FORWARD Forces the caster to move forward
    &AuraEffect::HandleNULL,                        // 242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - 2 test spells: 44183 and 44182
    &AuraEffect::HandleAuraModFaction,              // 243 SPELL_AURA_MOD_FACTION
    &AuraEffect::HandleComprehendLanguage,          // 244 SPELL_AURA_COMPREHEND_LANGUAGE
    &AuraEffect::HandleNoImmediateEffect,           // 245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
    &AuraEffect::HandleNoImmediateEffect,           // 246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura
    &AuraEffect::HandleAuraCloneCaster,             // 247 SPELL_AURA_CLONE_CASTER
    &AuraEffect::HandleNoImmediateEffect,           // 248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE         implemented in Unit::RollMeleeOutcomeAgainst
    &AuraEffect::HandleAuraConvertRune,             // 249 SPELL_AURA_CONVERT_RUNE
    &AuraEffect::HandleAuraModIncreaseHealth,       // 250 SPELL_AURA_MOD_INCREASE_HEALTH_2
    &AuraEffect::HandleNoImmediateEffect,           // 251 SPELL_AURA_MOD_ENEMY_DODGE
    &AuraEffect::HandleModCombatSpeedPct,           // 252 SPELL_AURA_252 Is there any difference between this and SPELL_AURA_MELEE_SLOW ? maybe not stacking mod?
    &AuraEffect::HandleNoImmediateEffect,           // 253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE  implemented in Unit::isBlockCritical
    &AuraEffect::HandleAuraModDisarm,               // 254 SPELL_AURA_MOD_DISARM_OFFHAND
    &AuraEffect::HandleNoImmediateEffect,           // 255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT    implemented in Unit::SpellDamageBonus
    &AuraEffect::HandleNoReagentUseAura,            // 256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
    &AuraEffect::HandleNULL,                        // 257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
    &AuraEffect::HandleNULL,                        // 258 SPELL_AURA_MOD_SPELL_VISUAL
    &AuraEffect::HandleNoImmediateEffect,           // 259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus
    &AuraEffect::HandleNoImmediateEffect,           // 260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
    &AuraEffect::HandlePhase,                       // 261 SPELL_AURA_PHASE undetactable invisibility?     implemented in Unit::isVisibleForOrDetect
    &AuraEffect::HandleNoImmediateEffect,           // 262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast
    &AuraEffect::HandleAuraAllowOnlyAbility,        // 263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
    &AuraEffect::HandleUnused,                      // 264 unused (3.2.0)
    &AuraEffect::HandleUnused,                      // 265 unused (3.2.0)
    &AuraEffect::HandleUnused,                      // 266 unused (3.2.0)
    &AuraEffect::HandleNoImmediateEffect,           // 267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL         implemented in Unit::IsImmunedToSpellEffect
    &AuraEffect::HandleAuraModAttackPowerOfStatPercent,// 268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
    &AuraEffect::HandleNoImmediateEffect,           // 269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
    &AuraEffect::HandleNoImmediateEffect,           // 270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
    &AuraEffect::HandleNoImmediateEffect,           // 271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER    implemented in Unit::SpellDamageBonus
    &AuraEffect::HandleNoImmediateEffect,           // 272 SPELL_AURA_IGNORE_MELEE_RESET
    &AuraEffect::HandleUnused,                      // 273 clientside
    &AuraEffect::HandleNoImmediateEffect,           // 274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets
    &AuraEffect::HandleNoImmediateEffect,           // 275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
    &AuraEffect::HandleNULL,                        // 276 mod damage % mechanic?
    &AuraEffect::HandleNoImmediateEffect,           // 277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
    &AuraEffect::HandleAuraModDisarm,               // 278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
    &AuraEffect::HandleNoImmediateEffect,           // 279 SPELL_AURA_INITIALIZE_IMAGES
    &AuraEffect::HandleNoImmediateEffect,           // 280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
    &AuraEffect::HandleNoImmediateEffect,           // 281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
    &AuraEffect::HandleAuraIncreaseBaseHealthPercent,// 282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
    &AuraEffect::HandleNoImmediateEffect,           // 283 SPELL_AURA_MOD_HEALING_RECEIVED       implemented in Unit::SpellHealingBonus
    &AuraEffect::HandleAuraLinked,                  // 284 SPELL_AURA_LINKED
    &AuraEffect::HandleAuraModAttackPowerOfArmor,   // 285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR  implemented in Player::UpdateAttackPowerAndDamage
    &AuraEffect::HandleNoImmediateEffect,           // 286 SPELL_AURA_ABILITY_PERIODIC_CRIT deprecated patch 4.0.1 all dots can crit
    &AuraEffect::HandleNoImmediateEffect,           // 287 SPELL_AURA_DEFLECT_SPELLS             implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
    &AuraEffect::HandleNoImmediateEffect,           // 288 SPELL_AURA_IGNORE_HIT_DIRECTION  implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst
    &AuraEffect::HandleNULL,                        // 289 unused (3.2.0)
    &AuraEffect::HandleAuraModCritPct,              // 290 SPELL_AURA_MOD_CRIT_PCT
    &AuraEffect::HandleNoImmediateEffect,           // 291 SPELL_AURA_MOD_XP_QUEST_PCT  implemented in Player::RewardQuest
    &AuraEffect::HandleAuraOpenStable,              // 292 SPELL_AURA_OPEN_STABLE
    &AuraEffect::HandleAuraOverrideSpells,          // 293 auras which probably add set of abilities to their target based on it's miscvalue
    &AuraEffect::HandleNoImmediateEffect,           // 294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
    &AuraEffect::HandleNULL,                        // 295 0 spells in 3.3.5
    &AuraEffect::HandleAuraSetVehicle,              // 296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target
    &AuraEffect::HandleNULL,                        // 297 Spirit Burst spells
    &AuraEffect::HandleNULL,                        // 298 70569 - Strangulating, maybe prevents talk or cast
    &AuraEffect::HandleNULL,                        // 299 unused
    &AuraEffect::HandleNoImmediateEffect,           // 300 SPELL_AURA_SHARE_DAMAGE_PCT implemented in Unit::DealDamage
    &AuraEffect::HandleNoImmediateEffect,           // 301 SPELL_AURA_SCHOOL_HEAL_ABSORB implemented in Unit::CalcHealAbsorb
    &AuraEffect::HandleNULL,                        // 302 0 spells in 3.3.5
    &AuraEffect::HandleNoImmediateEffect,           // 303 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
    &AuraEffect::HandleAuraModFakeInebriation,      // 304 SPELL_AURA_MOD_DRUNK
    &AuraEffect::HandleAuraModIncreaseSpeed,        // 305 SPELL_AURA_MOD_MINIMUM_SPEED
    &AuraEffect::HandleNULL,                        // 306 0 spells in 3.3.5
    &AuraEffect::HandleNULL,                        // 307 0 spells in 3.3.5
    &AuraEffect::HandleNULL,                        // 308 new aura for hunter traps
    &AuraEffect::HandleNULL,                        // 309 0 spells in 3.3.5
    &AuraEffect::HandleNoImmediateEffect,           // 310 SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE implemented in Spell::CalculateDamageDone
    &AuraEffect::HandleNULL,                        // 311 0 spells in 3.3.5
    &AuraEffect::HandleNULL,                        // 312 0 spells in 3.3.5
    &AuraEffect::HandleNULL,                        // 313 0 spells in 3.3.5
    &AuraEffect::HandleNoImmediateEffect,           // 314 SPELL_AURA_PREVENT_RESURRECTION todo
    &AuraEffect::HandleNoImmediateEffect,           // 315 SPELL_AURA_UNDERWATER_WALKING todo
    &AuraEffect::HandleNoImmediateEffect,           // 316 SPELL_AURA_PERIODIC_HASTE implemented in AuraEffect::CalculatePeriodic
    &AuraEffect::HandleAuraModSpellPowerPercent,    // 317 SPELL_AURA_MOD_SPELL_POWER_PCT
    &AuraEffect::HandleNoImmediateEffect,           // 318 SPELL_AURA_MASTERY
    &AuraEffect::HandleModMeleeSpeedPct,            // 319 This is actually mod haste (?)
    &AuraEffect::HandleNULL,                        // 320
    &AuraEffect::HandleNULL,                        // 321
    &AuraEffect::HandleNoImmediateEffect,           // 322 InterfereTargetting
    &AuraEffect::HandleNULL,                        // 323
    &AuraEffect::HandleNULL,                        // 324
    &AuraEffect::HandleNULL,                        // 325
    &AuraEffect::HandleNULL,                        // 326
    &AuraEffect::HandleNULL,                        // 327
    &AuraEffect::HandleNULL,                        // 328
    &AuraEffect::HandleNULL,                        // 329
    &AuraEffect::HandleNULL,                        // 330
    &AuraEffect::HandleNULL,                        // 331
    &AuraEffect::HandleAuraReplaceSpell,            // 332 SPELL_AURA_332_REPLACE_SPELL
    &AuraEffect::HandleAuraReplaceSpell,            // 333 SPELL_AURA_333_REPLACE_SPELL
    &AuraEffect::HandleNULL,                        // 334
    &AuraEffect::HandleNULL,                        // 335
    &AuraEffect::HandleNULL,                        // 336
    &AuraEffect::HandleAuraSaleForGuild,            // 337
    &AuraEffect::HandleNULL,                        // 338
    &AuraEffect::HandleNULL,                        // 339
    &AuraEffect::HandleNULL,                        // 340
    &AuraEffect::HandleNULL,                        // 341
    &AuraEffect::HandleNULL,                        // 342
    &AuraEffect::HandleNULL,                        // 343
    &AuraEffect::HandleNULL,                        // 344
    &AuraEffect::HandleNULL,                        // 345
    &AuraEffect::HandleNULL,                        // 346
    &AuraEffect::HandleNULL,                        // 347
    &AuraEffect::HandleNULL,                        // 348
    &AuraEffect::HandleNULL,                        // 349
    &AuraEffect::HandleNULL,                        // 350
    &AuraEffect::HandleNULL,                        // 351
    &AuraEffect::HandleNULL,                        // 352
    &AuraEffect::HandleModCamouflage,               // 353 SPELL_AURA_CAMOUFLAGE
};

AuraEffect::AuraEffect (Aura *base, uint8 effIndex, int32 *baseAmount, Unit *caster) :
        m_base(base), m_spellProto(base->GetSpellProto()), m_effIndex(effIndex), m_baseAmount(baseAmount ? *baseAmount : m_spellProto->EffectBasePoints[m_effIndex]), m_canBeRecalculated(true), m_spellmod(NULL), m_isPeriodic(false), m_periodicTimer(0), m_tickNumber(0)
{
    CalculatePeriodic(caster, true);

    m_amount = CalculateAmount(caster);

    CalculateSpellMod();

    if (m_spellProto)
        return;
}

AuraEffect::~AuraEffect ()
{
    delete m_spellmod;
}

void AuraEffect::GetTargetList (std::list<Unit *> & targetList) const
{
    Aura::ApplicationMap const & targetMap = GetBase()->GetApplicationMap();
    // remove all targets which were not added to new list - they no longer deserve area aura
    for (Aura::ApplicationMap::const_iterator appIter = targetMap.begin(); appIter != targetMap.end(); ++appIter)
    {
        if (appIter->second->HasEffect(GetEffIndex()))
            targetList.push_back(appIter->second->GetTarget());
    }
}

void AuraEffect::GetApplicationList (std::list<AuraApplication *> & applicationList) const
{
    Aura::ApplicationMap const & targetMap = GetBase()->GetApplicationMap();
    // remove all targets which were not added to new list - they no longer deserve area aura
    for (Aura::ApplicationMap::const_iterator appIter = targetMap.begin(); appIter != targetMap.end(); ++appIter)
    {
        if (appIter->second->HasEffect(GetEffIndex()))
            applicationList.push_back(appIter->second);
    }
}

int32 AuraEffect::CalculateAmount (Unit *caster)
{
    int32 amount;
    // default amount calculation
    amount = SpellMgr::CalculateSpellEffectAmount(m_spellProto, m_effIndex, caster, &m_baseAmount, NULL);

    // check item enchant aura cast
    if (!amount && caster)
        if (uint64 itemGUID = GetBase()->GetCastItemGUID())
            if (Player *playerCaster = dynamic_cast<Player*>(caster))
                if (Item *castItem = playerCaster->GetItemByGuid(itemGUID))
                    if (castItem->GetItemSuffixFactor())
                    {
                        ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
                        if (item_rand_suffix)
                        {
                            for (int k = 0; k < MAX_SPELL_EFFECTS; k++)
                            {
                                SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
                                if (pEnchant)
                                {
                                    for (int t = 0; t < MAX_SPELL_EFFECTS; t++)
                                        if (pEnchant->spellid[t] == m_spellProto->Id)
                                        {
                                            amount = uint32((item_rand_suffix->prefix[k] * castItem->GetItemSuffixFactor()) / 10000);
                                            break;
                                        }
                                }

                                if (amount)
                                    break;
                            }
                        }
                    }

    float DoneActualBenefit = 0.0f;

    // custom amount calculations go here
    switch (GetAuraType())
    {
    // crowd control auras
    case SPELL_AURA_MOD_CONFUSE:
    case SPELL_AURA_MOD_FEAR:
    case SPELL_AURA_MOD_STUN:
    case SPELL_AURA_MOD_ROOT:
    case SPELL_AURA_TRANSFORM:
        m_canBeRecalculated = false;
        if (!m_spellProto->procFlags)
            break;
        amount = int32(GetBase()->GetUnitOwner()->CountPctFromMaxHealth(10));
        if (caster)
        {
            // Glyphs increasing damage cap
            Unit::AuraEffectList const& overrideClassScripts = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
            for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr)
            {
                if ((*itr)->IsAffectedOnSpell(m_spellProto))
                {
                    // Glyph of Fear, Glyph of Frost nova and similar auras
                    if ((*itr)->GetMiscValue() == 7801)
                    {
                        amount += int32(amount * (*itr)->GetAmount() / 100.0f);
                        break;
                    }
                }
            }
        }
        break;
    case SPELL_AURA_SCHOOL_ABSORB:
        m_canBeRecalculated = false;
        if (!caster)
            break;
        switch (GetSpellProto()->SpellFamilyName)
        {
        case SPELLFAMILY_GENERIC:
            if (GetId() == 70845)
                DoneActualBenefit = caster->GetMaxHealth() * 0.2f;
            break;
        case SPELLFAMILY_MAGE:
            // Ice Barrier
            if (GetSpellProto()->SpellFamilyFlags[1] & 0x1 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
            {
                // +80.68% from sp bonus
                DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
                // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :)
                // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage
                DoneActualBenefit = float(caster->ApplyEffectModifiers(GetSpellProto(), m_effIndex, (int32) DoneActualBenefit));
            }
            // Fire Ward
            else if (GetSpellProto()->SpellFamilyFlags[0] & 0x8 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
            {
                // +80.68% from sp bonus
                DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
            }
            // Frost Ward
            else if (GetSpellProto()->SpellFamilyFlags[0] & 0x100 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
            {
                // +80.68% from sp bonus
                DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
            }
            break;
        case SPELLFAMILY_WARLOCK:
            // Shadow Ward
            if (m_spellProto->Id == 6229)
            {
                // +80.68% from sp bonus
                DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
            }
            break;
        case SPELLFAMILY_PRIEST:
            // Power Word: Shield
            // (SpellFamilyFlags[2] & 0x1 seems not work. Dbc flags: 0x00000000 00000000 00000001)
            if (GetId() == 17)
            {
                //+80.68% from sp bonus
                float bonus = 0.8068f;

                DoneActualBenefit += caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * bonus;
                DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
                amount += (int32) DoneActualBenefit;

                // Improved PW: Shield
                if (AuraEffect const* pAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 566, 1))
                    AddPctN(amount, pAurEff->GetAmount());

                // Spiritual Healing
                if (AuraEffect const* pAurEff = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 3131, 0))
                    AddPctN(amount, pAurEff->GetAmount());

                // Twin Disciplines
                DoneActualBenefit = float(amount);
                DoneActualBenefit *= caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
                amount = int32(DoneActualBenefit);

                // Mastery: Shield Discipline
                if (caster->ToPlayer()->HasAuraType(SPELL_AURA_MASTERY))
                {
                    if (caster->ToPlayer()->getClass() == CLASS_PRIEST)
                    {
                        if (caster->ToPlayer()->GetTalentBranchSpec(caster->ToPlayer()->GetActiveSpec()) == BS_PRIEST_DISCIPLINE)
                        {
                            int32 bp = int32(amount * (0.2f + (0.025f * caster->ToPlayer()->GetMasteryPoints())));
                            amount += bp;
                        }
                    }
                }
                return amount;
            }
            break;
        case SPELLFAMILY_PALADIN:
            // Sacred Shield
            if (m_spellProto->SpellFamilyFlags[1] & 0x80000)
            {
                //+75.00% from sp bonus
                float bonus = 0.75f;

                DoneActualBenefit += caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * bonus;
                // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage
                DoneActualBenefit = float(caster->ApplyEffectModifiers(GetSpellProto(), m_effIndex, (int32) DoneActualBenefit));
                DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());

                amount += (int32) DoneActualBenefit;

                // Arena - Dampening
                if (AuraEffect const* pAurEff = caster->GetAuraEffect(74410, 0))
                    amount *= int32((100.0f + pAurEff->GetAmount()) / 100.0f);
                // Battleground - Dampening
                else if (AuraEffect const* pAurEff = caster->GetAuraEffect(74411, 0))
                    amount *= int32((100.0f + pAurEff->GetAmount()) / 100.0f);

                return amount;
            }
            break;
        default:
            break;
        }
        break;
    case SPELL_AURA_MANA_SHIELD:
        m_canBeRecalculated = false;
        if (!caster)
            break;
        // Mana Shield
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellFamilyFlags[0] & 0x8000 && m_spellProto->SpellFamilyFlags[2] & 0x8)
        {
            // +80.53% from +spd bonus
            DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8053f;
            ;
        }
        break;
    case SPELL_AURA_DUMMY:
        if (!caster)
            break;
        // Earth Shield
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellProto->SpellFamilyFlags[1] & 0x400)
        {
            // return to unmodified by spellmods value
            amount = m_spellProto->EffectBasePoints[m_effIndex];
            // apply spell healing bonus
            amount = caster->SpellHealingBonus(GetBase()->GetUnitOwner(), GetSpellProto(), GetEffIndex(), amount, SPELL_DIRECT_DAMAGE);
            // apply spellmods
            amount = caster->ApplyEffectModifiers(GetSpellProto(), m_effIndex, float(amount));
        }
        break;
    case SPELL_AURA_DAMAGE_SHIELD:
        if (!caster)
            break;
        // Thorns
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x100)
            // 3.3% from sp bonus
            DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.033f;
        break;
    case SPELL_AURA_PERIODIC_DAMAGE:
        if (!caster)
            break;
        // Rupture
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x100000)
        {
            m_canBeRecalculated = false;
            if (caster->GetTypeId() != TYPEID_PLAYER)
                break;
            //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs
            //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs
            //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs
            //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs
            //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs
            float AP_per_combo[6] =
            { 0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f };
            uint8 cp = caster->ToPlayer()->GetComboPoints();
            if (cp > 5)
                cp = 5;
            amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
        }
        // Rip
        else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x00800000 && GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
        {
            m_canBeRecalculated = false;
            // 0.01*$AP*cp
            if (caster->GetTypeId() != TYPEID_PLAYER)
                break;

            uint8 cp = caster->ToPlayer()->GetComboPoints();

            // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
            if (AuraEffect const * aurEff = caster->GetAuraEffect(34241, 0))
                amount += cp * aurEff->GetAmount();

            amount += CalculatePctF(caster->GetTotalAttackPowerValue(BASE_ATTACK), cp);
        }
        // Rend
        else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellProto()->SpellFamilyFlags[0] & 0x20)
        {
            m_canBeRecalculated = false;
            // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
            float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
            int32 mws = caster->GetAttackTime(BASE_ATTACK);
            float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
            float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
            amount += caster->ApplyEffectModifiers(m_spellProto, m_effIndex, int32(((mwb_min + mwb_max) / 2 + ap * mws / 14000) * 0.2f));
            // "If used while your target is above 75% health, Rend does 35% more damage."
            // as for 3.1.3 only ranks above 9 (wrong tooltip?)
            if (sSpellMgr->GetSpellRank(m_spellProto->Id) >= 9)
                if (GetBase()->GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellProto, caster))
                    amount += int32(amount * SpellMgr::CalculateSpellEffectAmount(m_spellProto, 2, caster) / 100.0f);
        }
        // Unholy Blight damage over time effect
        else if (GetId() == 50536)
        {
            m_canBeRecalculated = false;
            // we're getting total damage on aura apply, change it to be damage per tick
            amount = int32((float) amount / GetTotalTicks());
        }
        break;
    case SPELL_AURA_PERIODIC_ENERGIZE:
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC)
        {
            // Replenishment (0.25% from max)
            // Infinite Replenishment
            if (m_spellProto->SpellIconID == 3184 && m_spellProto->SpellVisual[0] == 12495)
                amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 25 / 10000;
        }
        // Innervate
        else if (m_spellProto->Id == 29166)
        {
            int32 bonusMana = amount;
            if (GetBase()->GetCaster() == GetBase()->GetUnitOwner())
            {
                if (GetBase()->GetCaster()->HasAura(33597))          // Dreamstate rank1
                    bonusMana += 15;
                if (GetBase()->GetCaster()->HasAura(33599))          // Dreamstate rank2
                    bonusMana += 30;
            }
            amount = int32(GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount * 3 / (GetTotalTicks() * 100.0f));
        }
        // Owlkin Frenzy
        else if (m_spellProto->Id == 48391)
            amount = GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount / 100;
        break;
    case SPELL_AURA_PERIODIC_HEAL:
        if (!caster)
            break;
        // Lightwell Renew
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->SpellFamilyFlags[2] & 0x4000)
        {
            if (caster->GetTypeId() == TYPEID_PLAYER)
                // Bonus from Glyph of Lightwell
                if (AuraEffect* modHealing = caster->GetAuraEffect(55673, 0))
                    amount = int32(amount * (100.0f + modHealing->GetAmount()) / 100.0f);
            // Bonus from talent Spiritual Healing
            if (AuraEffect* modHealing = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 46, 1))
                AddPctN(amount, modHealing->GetAmount());
        }
        break;
    case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
        if (!caster)
            break;
        // Icebound Fortitude
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellProto->SpellFamilyFlags[0] & 0x00100000)
        {
            if (caster->GetTypeId() == TYPEID_PLAYER)
            {
                int32 value = -amount;

                // Glyph of Icebound Fortitude
                if (AuraEffect const * aurEff = caster->GetAuraEffect(58625, 0))
                    value = aurEff->GetAmount();

                uint32 defval = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
                if (defval > 400)
                    value += int32((defval - 400) * 0.075);

                amount = -value;
            }
        }
        // Hand of Salvation
        else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PALADIN && GetSpellProto()->SpellFamilyFlags[0] & 0x00000100)
        {
            //Glyph of Salvation
            if (caster->GetGUID() == GetBase()->GetUnitOwner()->GetGUID())
                if (AuraEffect const * aurEff = caster->GetAuraEffect(63225, 0))
                    amount = -aurEff->GetAmount();
        }
        break;
    case SPELL_AURA_MOD_THREAT:
    {
        uint8 level_diff = 0;
        float multiplier = 0.0;
        switch (GetId())
        {
        // Arcane Shroud
        case 26400:
            level_diff = GetBase()->GetUnitOwner()->getLevel() - 60;
            multiplier = 2;
            break;
            // The Eye of Diminution
        case 28862:
            level_diff = GetBase()->GetUnitOwner()->getLevel() - 60;
            multiplier = 1;
            break;
        }
        if (level_diff > 0)
            amount += int32(multiplier * level_diff);
        break;
    }
    case SPELL_AURA_MOD_INCREASE_HEALTH:
        // Vampiric Blood
        if (GetId() == 55233)
            amount = GetBase()->GetUnitOwner()->CountPctFromMaxHealth(amount);
         // Last Stand Warrior
        if (GetId() == 12976)
            amount = GetBase()->GetUnitOwner()->CountPctFromMaxHealth(30);
        // Last Stand Hunter
        if (GetId() == 53478)
            amount = GetBase()->GetUnitOwner()->CountPctFromMaxHealth(30);
        break;
    case SPELL_AURA_MOD_INCREASE_ENERGY:
        // Hymn of Hope
        if (GetId() == 64904)
            amount = GetBase()->GetUnitOwner()->GetMaxPower(GetBase()->GetUnitOwner()->getPowerType()) * amount / 100;
        break;
    case SPELL_AURA_MOD_INCREASE_SPEED:
        // Dash - do not set speed if not in cat form
        if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags[2] & 0x00000008)
            amount = GetBase()->GetUnitOwner()->GetShapeshiftForm() == FORM_CAT ? amount : 0;
        break;
    case SPELL_AURA_MOUNTED:
    {
        Player *plr = caster->ToPlayer();
        if (plr)
        {
            // find the spell we need
            const MountTypeEntry *type = sMountTypeStore.LookupEntry(GetMiscValueB());
            if (!type)
                return 0;

            uint32 spellId = 0;
            uint32 plrskill = plr->GetSkillValue(SKILL_RIDING);
            uint32 map = GetVirtualMapForMapAndZone(plr->GetMapId(), plr->GetZoneId());
            uint32 maxSkill = 0;
            for (int i = 0; i < MAX_MOUNT_TYPE_COLUMN; i++)
            {
                const MountCapabilityEntry *cap = sMountCapabilityStore.LookupEntry(type->capabilities[i]);
                if (!cap)
                    continue;
                if (cap->map != ((uint32) -1) && cap->map != map)
                    continue;
                if (cap->reqSkillLevel && (cap->reqSkillLevel > plrskill || cap->reqSkillLevel <= maxSkill))
                    continue;
                if (cap->reqSpell && !plr->HasSpell(cap->reqSpell))
                    continue;
                maxSkill = cap->reqSkillLevel;
                spellId = cap->spell;
            }
            return (int) spellId;
        }
        break;
    }
    case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE:
    {
        if (caster)
        {
            int32 resist = caster->getLevel();
            if (resist <= 70)
            {
            }
            else if (resist > 70 && resist < 81)
            {
                resist += (resist - 70) * 5;
            }
            else if (resist > 80 && resist <= 85)
            {
                resist += ((resist - 70) * 5 + (resist - 80) * 7);
            }
            switch (GetId())
            {
            case 20043:          // Aspect of the Wild
            case 8185:          // Elemental Resistance
            case 19891:          // Resistance Aura
            case 79106:          // Shadow Protection
                amount = resist;
                break;
            case 79060:          // Mark of the Wild
            case 79062:          // Blessing of Kings
                amount = resist / 2;
                break;
            }
            break;
        }
    }
    default:
        break;
    }
    if (DoneActualBenefit != 0.0f)
    {
        DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
        amount += (int32) DoneActualBenefit;
    }

    GetBase()->CallScriptEffectCalcAmountHandlers(const_cast<AuraEffect const *>(this), amount, m_canBeRecalculated);
    amount *= GetBase()->GetStackAmount();
    return amount;
}

void AuraEffect::CalculatePeriodic (Unit *caster, bool create)
{
    m_amplitude = m_spellProto->EffectAmplitude[m_effIndex];

    // prepare periodics
    switch (GetAuraType())
    {
    case SPELL_AURA_OBS_MOD_POWER:
        // 3 spells have no amplitude set
        if (!m_amplitude)
            m_amplitude = 1 * IN_MILLISECONDS;
    case SPELL_AURA_PERIODIC_DAMAGE:
    case SPELL_AURA_PERIODIC_HEAL:
    case SPELL_AURA_PERIODIC_ENERGIZE:
    case SPELL_AURA_OBS_MOD_HEALTH:
    case SPELL_AURA_PERIODIC_LEECH:
    case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
    case SPELL_AURA_PERIODIC_MANA_LEECH:
    case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
    case SPELL_AURA_POWER_BURN:
        m_isPeriodic = true;
        break;
    case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
        if (GetId() == 51912)
            m_amplitude = 3000;
        m_isPeriodic = true;
        break;
    case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
    case SPELL_AURA_PERIODIC_DUMMY:
        m_isPeriodic = true;
        break;
    case SPELL_AURA_DUMMY:
        // Haunting Spirits
        if (GetId() == 7057)
        {
            m_isPeriodic = true;
            m_amplitude = irand(0, 60) + 30;
            m_amplitude *= IN_MILLISECONDS;
        }
        break;
    default:
        break;
    }

    GetBase()->CallScriptEffectCalcPeriodicHandlers(const_cast<AuraEffect const *>(this), m_isPeriodic, m_amplitude);

    if (!m_isPeriodic)
        return;

    Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;

    // Apply casting time mods
    if (m_amplitude)
    {
        // Apply periodic time mod
        if (modOwner)
            modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_amplitude);

        if (caster)
        {
            // Haste modifies periodic time of channeled spells
            if (IsChanneledSpell(m_spellProto))
            {
                if (m_spellProto->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
                    caster->ModSpellCastTime(m_spellProto, m_amplitude);
            }
            // and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
            else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellProto) || m_spellProto->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
                m_amplitude = int32(m_amplitude * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
        }
    }

    if (create)
    {
        // Start periodic on next tick or at aura apply
        if (m_amplitude && !(m_spellProto->AttributesEx5 & SPELL_ATTR5_START_PERIODIC_AT_APPLY))
            m_periodicTimer += m_amplitude;
    }
    else if (m_amplitude)          // load aura from character_aura
    {
        m_tickNumber = GetBase()->GetDuration() / m_amplitude;
        m_periodicTimer = GetBase()->GetDuration() % m_amplitude;
        if (m_spellProto->AttributesEx5 & SPELL_ATTR5_START_PERIODIC_AT_APPLY)
            ++m_tickNumber;
    }
}

void AuraEffect::CalculateSpellMod ()
{
    switch (GetAuraType())
    {
    case SPELL_AURA_DUMMY:
        switch (GetSpellProto()->SpellFamilyName)
        {
        case SPELLFAMILY_PRIEST:
            // Pain and Suffering
            if (m_spellProto->SpellIconID == 2874)
            {
                if (!m_spellmod)
                {
                    m_spellmod = new SpellModifier(GetBase());
                    m_spellmod->op = SPELLMOD_DOT;
                    m_spellmod->type = SPELLMOD_PCT;
                    m_spellmod->spellId = GetId();
                    m_spellmod->mask[1] = 0x00002000;
                }
                m_spellmod->value = GetAmount();
            }
            break;
        case SPELLFAMILY_DRUID:
            switch (GetId())
            {
            case 34246:          // Idol of the Emerald Queen
            case 60779:          // Idol of Lush Moss
            {
                if (!m_spellmod)
                {
                    m_spellmod = new SpellModifier(GetBase());
                    m_spellmod->op = SPELLMOD_DOT;
                    m_spellmod->type = SPELLMOD_FLAT;
                    m_spellmod->spellId = GetId();
                    m_spellmod->mask[1] = 0x0010;
                }
                m_spellmod->value = GetAmount() / 7;
            }
                break;
            }
            break;
        default:
            break;
        }
    case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
        switch (GetId())
        {
        case 51466:          // Elemental oath
        case 51470:          // Elemental oath
            // "while Clearcasting from Elemental Focus is active, you deal 5%/10% more spell damage."
            if (!m_spellmod)
            {
                m_spellmod = new SpellModifier(GetBase());
                m_spellmod->op = SPELLMOD_EFFECT2;
                m_spellmod->type = SPELLMOD_FLAT;
                m_spellmod->spellId = GetId();
                m_spellmod->mask[1] = 0x0004000;
            }
            m_spellmod->value = GetBase()->GetUnitOwner()->CalculateSpellDamage(GetBase()->GetUnitOwner(), GetSpellProto(), 1);
            break;
        default:
            break;
        }
        break;
    case SPELL_AURA_ADD_FLAT_MODIFIER:
    case SPELL_AURA_ADD_PCT_MODIFIER:
        if (!m_spellmod)
        {
            m_spellmod = new SpellModifier(GetBase());
            m_spellmod->op = SpellModOp(GetMiscValue());
            ASSERT(m_spellmod->op < MAX_SPELLMOD);

            m_spellmod->type = SpellModType(GetAuraType());          // SpellModType value == spell aura types
            m_spellmod->spellId = GetId();
            m_spellmod->mask = GetSpellProto()->EffectSpellClassMask[GetEffIndex()];
            m_spellmod->charges = GetBase()->GetCharges();
        }
        m_spellmod->value = GetAmount();
        break;
    default:
        break;
    }
    GetBase()->CallScriptEffectCalcSpellModHandlers(const_cast<AuraEffect const *>(this), m_spellmod);
}

void AuraEffect::ChangeAmount (int32 newAmount, bool mark)
{
    //Unit *caster = GetCaster();
    // Reapply if amount change
    if (newAmount != GetAmount())
    {
        UnitList targetList;
        GetTargetList(targetList);
        for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget)
        {
            HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false);
        }
        if (!mark)
            m_amount = newAmount;
        else
            SetAmount(newAmount);
        CalculateSpellMod();
        for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget)
        {
            HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, true);
        }
    }
}

void AuraEffect::HandleEffect (AuraApplication const *aurApp, uint8 mode, bool apply)
{
    // check if call is correct
    ASSERT(!mode || mode == AURA_EFFECT_HANDLE_REAL || mode == AURA_EFFECT_HANDLE_SEND_FOR_CLIENT || mode == AURA_EFFECT_HANDLE_CHANGE_AMOUNT || mode == AURA_EFFECT_HANDLE_STAT);

    // real aura apply/remove, handle modifier
    if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
        ApplySpellMod(aurApp->GetTarget(), apply);

    bool prevented = false;
    if (apply)
        prevented = GetBase()->CallScriptEffectApplyHandlers(const_cast<AuraEffect const *>(this), aurApp, (AuraEffectHandleModes) mode);
    else
        prevented = GetBase()->CallScriptEffectRemoveHandlers(const_cast<AuraEffect const *>(this), aurApp, (AuraEffectHandleModes) mode);

    // check if script events have removed the aura or if default effect prevention was requested
    if ((apply && aurApp->GetRemoveMode()) || prevented)
        return;

    (*this.*AuraEffectHandler[GetAuraType()])(aurApp, mode, apply);
}

void AuraEffect::HandleEffect (Unit *target, uint8 mode, bool apply)
{
    AuraApplication const *aurApp = GetBase()->GetApplicationOfTarget(target->GetGUID());
    ASSERT(aurApp);
    HandleEffect(aurApp, mode, apply);
}

void AuraEffect::ApplySpellMod (Unit *target, bool apply)
{
    if (!m_spellmod || target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ToPlayer()->AddSpellMod(m_spellmod, apply);

    // Auras with charges do not mod amount of passive auras
    if (GetBase()->GetCharges())
        return;
    // reapply some passive spells after add/remove related spellmods
    // Warning: it is a dead loop if 2 auras each other amount-shouldn't happen
    switch (GetMiscValue())
    {
    case SPELLMOD_ALL_EFFECTS:
    case SPELLMOD_EFFECT1:
    case SPELLMOD_EFFECT2:
    case SPELLMOD_EFFECT3:
    {
        uint64 guid = target->GetGUID();
        Unit::AuraApplicationMap & auras = target->GetAppliedAuras();
        for (Unit::AuraApplicationMap::iterator iter = auras.begin(); iter != auras.end(); ++iter)
        {
            Aura *aura = iter->second->GetBase();
            // only passive auras-active auras should have amount set on spellcast and not be affected
            // if aura is casted by others, it will not be affected
            if ((aura->IsPassive() || aura->GetSpellProto()->AttributesEx2 & SPELL_ATTR2_ALWAYS_APPLY_MODIFIERS) && aura->GetCasterGUID() == guid && sSpellMgr->IsAffectedByMod(aura->GetSpellProto(), m_spellmod))
            {
                if (GetMiscValue() == SPELLMOD_ALL_EFFECTS)
                {
                    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
                    {
                        if (AuraEffect * aurEff = aura->GetEffect(i))
                            aurEff->RecalculateAmount();
                    }
                }
                else if (GetMiscValue() == SPELLMOD_EFFECT1)
                {
                    if (AuraEffect * aurEff = aura->GetEffect(0))
                        aurEff->RecalculateAmount();
                }
                else if (GetMiscValue() == SPELLMOD_EFFECT2)
                {
                    if (AuraEffect * aurEff = aura->GetEffect(1))
                        aurEff->RecalculateAmount();
                }
                else
                {
                    if (AuraEffect * aurEff = aura->GetEffect(2))
                        aurEff->RecalculateAmount();
                }
            }
        }
    }
    default:
        break;
    }
}

void AuraEffect::Update (uint32 diff, Unit *caster)
{
    if (m_isPeriodic && (GetBase()->GetDuration() >= 0 || GetBase()->IsPassive() || GetBase()->IsPermanent()))
    {
        if (m_periodicTimer > int32(diff))
            m_periodicTimer -= diff;
        else          // tick also at m_periodicTimer == 0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
        {
            ++m_tickNumber;

            // update before tick (aura can be removed in TriggerSpell or PeriodicTick calls)
            m_periodicTimer += m_amplitude - diff;
            UpdatePeriodic(caster);

            std::list<AuraApplication*> effectApplications;
            GetApplicationList(effectApplications);
            // tick on targets of effects
            if (!caster || !caster->HasUnitState(UNIT_STAT_ISOLATED))
            {
                for (std::list<AuraApplication*>::iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr)
                    PeriodicTick(*apptItr, caster);
            }
        }
    }
}

void AuraEffect::UpdatePeriodic (Unit *caster)
{
    switch (GetAuraType())
    {
    case SPELL_AURA_DUMMY:
        // Haunting Spirits
        if (GetId() == 7057)
        {
            m_amplitude = irand(0, 60) + 30;
            m_amplitude *= IN_MILLISECONDS;
        }
        break;
    case SPELL_AURA_PERIODIC_DUMMY:
        switch (GetSpellProto()->SpellFamilyName)
        {
        case SPELLFAMILY_GENERIC:
            switch (GetId())
            {
            // Drink
            case 430:
            case 431:
            case 432:
            case 1133:
            case 1135:
            case 1137:
            case 10250:
            case 22734:
            case 27089:
            case 34291:
            case 43182:
            case 43183:
            case 46755:
            case 49472:          // Drink Coffee
            case 57073:
            case 61830:
            case 69176:
            case 72623:
            case 80166:
            case 80167:
            case 87958:
            case 87959:
            case 92736:
            case 92797:
            case 92800:
            case 92803:
                if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
                    return;
                // Get SPELL_AURA_MOD_POWER_REGEN aura from spell
                if (AuraEffect * aurEff = GetBase()->GetEffect(0))
                {
                    if (aurEff->GetAuraType() != SPELL_AURA_MOD_POWER_REGEN)
                    {
                        m_isPeriodic = false;
                        sLog->outError("Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", GetId());
                    }
                    else
                    {
                        // default case - not in arena
                        if (!caster->ToPlayer()->InArena())
                        {
                            aurEff->ChangeAmount(GetAmount());
                            m_isPeriodic = false;
                        }
                        else
                        {
                            // **********************************************
                            // This feature uses only in arenas
                            // **********************************************
                            // Here need increase mana regen per tick (6 second rule)
                            // on 0 tick -   0  (handled in 2 second)
                            // on 1 tick - 166% (handled in 4 second)
                            // on 2 tick - 133% (handled in 6 second)

                            // Apply bonus for 1 - 4 tick
                            switch (m_tickNumber)
                            {
                            case 1:          // 0%
                                aurEff->ChangeAmount(0);
                                break;
                            case 2:          // 166%
                                aurEff->ChangeAmount(GetAmount() * 5 / 3);
                                break;
                            case 3:          // 133%
                                aurEff->ChangeAmount(GetAmount() * 4 / 3);
                                break;
                            default:          // 100% - normal regen
                                aurEff->ChangeAmount(GetAmount());
                                // No need to update after 4th tick
                                m_isPeriodic = false;
                                break;
                            }
                        }
                    }
                }
                break;
            case 58549:          // Tenacity
            case 59911:          // Tenacity (vehicle)
                GetBase()->RefreshDuration();
                break;
            case 66823:
            case 67618:
            case 67619:
            case 67620:          // Paralytic Toxin
                // Get 0 effect aura
                if (AuraEffect *slow = GetBase()->GetEffect(0))
                {
                    int32 newAmount = slow->GetAmount() - 10;
                    if (newAmount < -100)
                        newAmount = -100;
                    slow->ChangeAmount(newAmount);
                }
                break;
            default:
                break;
            }
            break;
        case SPELLFAMILY_MAGE:
            if (GetId() == 55342)          // Mirror Image
                m_isPeriodic = false;
            break;
        case SPELLFAMILY_DEATHKNIGHT:
            // Chains of Ice
            if (GetSpellProto()->SpellFamilyFlags[1] & 0x00004000)
            {
                // Get 0 effect aura
                if (AuraEffect *slow = GetBase()->GetEffect(0))
                {
                    int32 newAmount = slow->GetAmount() + GetAmount();
                    if (newAmount > 0)
                        newAmount = 0;
                    slow->ChangeAmount(newAmount);
                }
                return;
            }
            break;
        default:
            break;
        }
    default:
        break;
    }
    GetBase()->CallScriptEffectUpdatePeriodicHandlers(this);
}

bool AuraEffect::IsPeriodicTickCrit (Unit *target, Unit const *caster) const
{
    ASSERT(caster);
    if (caster->isSpellCrit(target, m_spellProto, GetSpellSchoolMask(m_spellProto)))
        return true;
    else
        return false;
}

void AuraEffect::SendTickImmune (Unit *target, Unit *caster) const
{
    if (caster)
        caster->SendSpellDamageImmune(target, m_spellProto->Id);
}

void AuraEffect::PeriodicTick (AuraApplication * aurApp, Unit * caster) const
{
    bool prevented = GetBase()->CallScriptEffectPeriodicHandlers(this, aurApp);
    if (prevented)
        return;

    Unit * target = aurApp->GetTarget();

    switch (GetAuraType())
    {
    case SPELL_AURA_PERIODIC_DAMAGE:
    case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
    {
        if (!caster)
            break;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        // Consecrate ticks can miss and will not show up in the combat log
        if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
            break;

        // Check for immune (not use charges)
        if (target->IsImmunedToDamage(GetSpellProto()))
        {
            SendTickImmune(target, caster);
            break;
        }

        // Dark Evangelism
        if (target->HasAura(15407))          // Mind Flay
        {
            if (caster->HasAura(81659))          // Rank 1
                caster->CastSpell(caster, 87117, true);
            else if (caster->HasAura(81662))          // Rank 2
                caster->CastSpell(caster, 87118, true);

            caster->AddAura(87154, caster);
        }

        // some auras remove at specific health level or more
        if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
        {
            switch (GetId())
            {
            case 43093:
            case 31956:
            case 38801:          // Grievous Wound
            case 35321:
            case 38363:
            case 39215:          // Gushing Wound
                if (target->IsFullHealth())
                {
                    target->RemoveAurasDueToSpell(GetId());
                    return;
                }
                break;
            case 38772:          // Grievous Wound
            {
                uint32 percent = GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_DUMMY ? caster->CalculateSpellDamage(target, GetSpellProto(), GetEffIndex() + 1) : 100;
                if (!target->HealthBelowPct(percent))
                {
                    target->RemoveAurasDueToSpell(GetId());
                    return;
                }
                break;
            }
            case 603:          // Bane of Doom
            {
                // There is a chance to summon an Ebon Imp when Bane of Doom does damage
                if (roll_chance_i(20))
                    caster->CastSpell(caster, 18662, true);

                break;
            }
            case 589:          // Shadow Word: Pain
                if (AuraEffect* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 4879, 0))
                {
                    int32 chance = aurEff->GetAmount();
                    if (caster->isMoving())
                        chance *= 5;

                    std::list<Creature*> unitList;
                    caster->GetCreatureListWithEntryInGrid(unitList, 46954, 100.0f);
                    uint32 appCount = 0;
                    for (std::list<Creature*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
                    {
                        if ((*itr)->GetOwnerGUID() == caster->GetGUID())
                            appCount++;
                    }

                    if (roll_chance_i(chance) && appCount < 4)
                    {
                        caster->CastSpell(target, 87426, true);
                    }
                }
                break;
            }
        }

        uint32 absorb = 0;
        uint32 resist = 0;
        CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);

        // ignore non positive values (can be result apply spellmods to aura damage
        uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
        damage = int32(damage / 2);

        if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
        {
            damage += caster->SpellDamageBonus(target, GetSpellProto(), GetEffIndex(), damage, DOT, GetBase()->GetStackAmount());

            // Calculate armor mitigation
            if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
            {
                uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
                cleanDamage.mitigated_damage += damage - damageReductedArmor;
                damage = damageReductedArmor;
            }

            //Shadow Word Death/Mind Blast Shadow Orb Proc 10% chance in 406a
			if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (GetSpellProto()->SpellIconID == 95 || GetSpellProto()->SpellIconID == 1980)) // Mind Blast / Shadow Word Death
			{
				int32 orbchance = 10;
				if (roll_chance_i(orbchance))
					caster->CastSpell(caster, 95740, true);
			}
			// Curse of Agony damage-per-tick calculation
            if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID == 544)
            {
                uint32 totalTick = GetTotalTicks();
                // 1..4 ticks, 1/2 from normal tick damage
                if (m_tickNumber <= totalTick / 3)
                    damage = damage / 2;
                // 9..12 ticks, 3/2 from normal tick damage
                else if (m_tickNumber > totalTick * 2 / 3)
                    damage += (damage + 1) / 2;          // +1 prevent 0.5 damage possible lost at 1..4 ticks
                // 5..8 ticks have normal tick damage
            }

            // Explosive Shot
            if (GetSpellProto()->Id == 53301)
                damage = int32(damage + (0.232f * GetBase()->GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK)));

            // Serpent Sting
            if (GetSpellProto()->Id == 1978)
                damage = int32((GetBase()->GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.4f + (damage * 15 / 3)) / 5);

            if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC)
            {
                switch (GetId())
                {
                case 70911:          // Unbound Plague
                case 72854:          // Unbound Plague
                case 72855:          // Unbound Plague
                case 72856:          // Unbound Plague
                    damage *= uint32(pow(1.25f, int32(m_tickNumber)));
                    break;
                default:
                    break;
                }
            }
        }
        else
            damage = uint32(target->CountPctFromMaxHealth(damage));

        bool crit = IsPeriodicTickCrit(target, caster);
        if (crit)
            damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);

        int32 dmg = damage;
        caster->ApplyResilience(target, &dmg);
        damage = dmg;

        caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);

        sLog->outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);

        caster->DealDamageMods(target, damage, &absorb);

        // Set trigger flag
        uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
        uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
        uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
        damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist);
        if (damage)
            procVictim |= PROC_FLAG_TAKEN_DAMAGE;

        int32 overkill = damage - target->GetHealth();
        if (overkill < 0)
            overkill = 0;

        SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
        target->SendPeriodicAuraLog(&pInfo);

        caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());

        caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
        break;
    }
    case SPELL_AURA_PERIODIC_LEECH:
    {
        if (!caster)
            return;

        if (!caster->isAlive())
            return;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
            return;

        // Check for immune
        if (target->IsImmunedToDamage(GetSpellProto()))
        {
            SendTickImmune(target, caster);
            return;
        }

        uint32 absorb = 0;
        uint32 resist = 0;
        CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);

        uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
        damage = caster->SpellDamageBonus(target, GetSpellProto(), GetEffIndex(), damage, DOT, GetBase()->GetStackAmount());

        bool crit = IsPeriodicTickCrit(target, caster);
        if (crit)
            damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);

        // Calculate armor mitigation
        if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
        {
            uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
            cleanDamage.mitigated_damage += damage - damageReductedArmor;
            damage = damageReductedArmor;
        }

        int32 dmg = damage;
        caster->ApplyResilience(target, &dmg);
        damage = dmg;

        caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);

        if (target->GetHealth() < damage)
            damage = uint32(target->GetHealth());

        sLog->outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);

        caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit);

        // Set trigger flag
        uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
        uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
        uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
        damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist);
        if (damage)
            procVictim |= PROC_FLAG_TAKEN_DAMAGE;
        caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
        int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);

        if (!target->isAlive() && caster->IsNonMeleeSpellCasted(false))
            for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
                if (Spell* spell = caster->GetCurrentSpell(CurrentSpellTypes(i)))
                    if (spell->m_spellInfo->Id == GetId())
                        spell->cancel();

        float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);

        uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellProto(), GetEffIndex(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));

        int32 gain = caster->HealBySpell(caster, GetSpellProto(), heal);
        caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellProto());
        break;
    }
    case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:          // only three spells
    {
        if (!caster || !caster->GetHealth())
            break;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        uint32 damage = GetAmount();
        // do not kill health donator
        if (caster->GetHealth() < damage)
            damage = caster->GetHealth() - 1;
        if (!damage)
            break;

        caster->ModifyHealth(-(int32) damage);
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "PeriodicTick: donator %u target %u damage %u.", target->GetEntry(), target->GetEntry(), damage);

        float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);

        damage = int32(damage * gainMultiplier);

        caster->HealBySpell(target, GetSpellProto(), damage);
        break;
    }
    case SPELL_AURA_PERIODIC_HEAL:
    case SPELL_AURA_OBS_MOD_HEALTH:
    {
        if (!caster)
            break;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        // heal for caster damage (must be alive)
        if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL && !caster->isAlive())
            break;

        if (GetBase()->GetDuration() == -1 && target->IsFullHealth())
            break;

        // ignore non positive values (can be result apply spellmods to aura damage
        int32 damage = m_amount > 0 ? m_amount : 0;

        if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
        {
            // Taken mods
            float TakenTotalMod = 1.0f;

            // Tenacity increase healing % taken
            if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0))
                TakenTotalMod *= (Tenacity->GetAmount() + 100.0f) / 100.0f;

            // Healing taken percent
            float minval = (float) target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
            if (minval)
                TakenTotalMod *= (100.0f + minval) / 100.0f;

            float maxval = (float) target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
            if (maxval)
                TakenTotalMod *= (100.0f + maxval) / 100.0f;

            // Healing over time taken percent
            float minval_hot = (float) target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
            if (minval_hot)
                TakenTotalMod *= (100.0f + minval_hot) / 100.0f;

            float maxval_hot = (float) target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
            if (maxval_hot)
                TakenTotalMod *= (100.0f + maxval_hot) / 100.0f;

            TakenTotalMod = TakenTotalMod > 0.0f ? TakenTotalMod : 0.0f;

            damage = uint32(target->CountPctFromMaxHealth(damage));
            damage = uint32(damage * TakenTotalMod);

            switch (m_spellProto->Id)
            {
            uint32 dmg;
        case 16488:          // Blood Craze Rank 1
            dmg = caster->GetMaxHealth() / 100 * 0.2;
            damage = dmg;
            break;
        case 16490:          // Blod Craze Rank 2
            dmg = caster->GetMaxHealth() / 100 * 0.4;
            damage = dmg;
            break;
        case 16491:          // Blod Craze Rank 3
            dmg = caster->GetMaxHealth() / 100 * 0.6;
            damage = dmg;
            break;
        default:
            break;
            }
        }
        else
        {
            // Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100
            int32 addition = 0;
            if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864)
                addition = int32(float(damage * GetTotalTicks()) * ((6 - float(2 * (GetTickNumber() - 1))) / 100));

            // Item - Druid T10 Restoration 2P Bonus
            if (AuraEffect * aurEff = caster->GetAuraEffect(70658, 0))
                addition += abs(int32((addition * aurEff->GetAmount()) / 50));

            damage += addition;
            damage = caster->SpellHealingBonus(target, GetSpellProto(), GetEffIndex(), damage, DOT, GetBase()->GetStackAmount());
        }
        switch (m_spellProto->Id)
        {
        case 774:
        {
            float bonus = 1.0f;
            if (caster->HasAura(78784))          // Blessing of the Grove rank 1
                bonus += 0.02f;
            if (caster->HasAura(78785))          // Blessing of the Grove rank 2
                bonus += 0.04f;
            damage = int32(damage * bonus);
            break;
        }
        case 29841:          // Second Wind r1
            damage = int32(caster->GetMaxHealth() * 0.004f);
            break;
        case 29842:          // Second Wind r2
        case 42771:          // Second Wind r2
            damage = int32(caster->GetMaxHealth() * 0.01f);
            break;
        case 8936:          // Recrecimiento
            if (caster->HasAura(54743) && target->HealthBelowPct(50))
                this->GetBase()->RefreshDuration();
            break;
        default:
            break;
        }

        bool crit = IsPeriodicTickCrit(target, caster);
        if (crit)
            damage = caster->SpellCriticalHealingBonus(m_spellProto, damage, target);

        sLog->outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());

        uint32 absorb = 0;
        uint32 heal = uint32(damage);
        caster->CalcHealAbsorb(target, GetSpellProto(), heal, absorb);
        int32 gain = caster->DealHeal(target, heal);

        SpellPeriodicAuraLogInfo pInfo(this, damage, damage - gain, absorb, 0, 0.0f, crit);
        target->SendPeriodicAuraLog(&pInfo);

        target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());

        bool haveCastItem = GetBase()->GetCastItemGUID() != 0;

        // Health Funnel
        // damage caster for heal amount
        if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL)
        {
            uint32 damage = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), 0);          // damage is not affected by spell power
            if ((int32) damage > gain)
                damage = gain;
            uint32 absorb = 0;
            caster->DealDamageMods(caster, damage, &absorb);
            caster->SendSpellNonMeleeDamageLog(caster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);

            CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
            caster->DealDamage(caster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
        }

        uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
        uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
        uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_HOT;
        // ignore item heals
        if (!haveCastItem)
            caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
        break;
    }
    case SPELL_AURA_PERIODIC_MANA_LEECH:
    {
        if (GetMiscValue() < 0 || GetMiscValue() >= int8(MAX_POWERS))
            break;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        Powers power = Powers(GetMiscValue());

        // power type might have changed between aura applying and tick (druid's shapeshift)
        if (target->getPowerType() != power)
            break;

        if (!caster || !caster->isAlive())
            break;

        if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
            break;

        // Check for immune (not use charges)
        if (target->IsImmunedToDamage(GetSpellProto()))
        {
            SendTickImmune(target, caster);
            break;
        }

        // ignore non positive values (can be result apply spellmods to aura damage
        uint32 damage = m_amount > 0 ? m_amount : 0;

        // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
        // It's mana percent cost spells, m_amount is percent drain from target
        if (m_spellProto->ManaCostPercentage)
        {
            // max value
            uint32 maxmana = caster->GetMaxPower(power) * damage * 2 / 100;
            damage = target->GetMaxPower(power) * damage / 100;
            if (damage > maxmana)
                damage = maxmana;
        }

        sLog->outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());

        int32 drain_amount = target->GetPower(power) > damage ? damage : target->GetPower(power);

        target->ModifyPower(power, -drain_amount);

        float gain_multiplier = 0.0f;

        if (caster->GetMaxPower(power) > 0)
            gain_multiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);

        SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier, false);
        target->SendPeriodicAuraLog(&pInfo);

        int32 gain_amount = int32(drain_amount * gain_multiplier);

        if (gain_amount)
        {
            int32 gain = caster->ModifyPower(power, gain_amount);
            target->AddThreat(caster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
        }

        switch (GetId())
        {
        case 31447:          // Mark of Kaz'rogal
            if (target->GetPower(power) == 0)
            {
                target->CastSpell(target, 31463, true, 0, this);
                // Remove aura
                GetBase()->SetDuration(0);
            }
            break;

        case 32960:          // Mark of Kazzak
            int32 modifier = int32(target->GetPower(power) * 0.05f);
            target->ModifyPower(power, -modifier);

            if (target->GetPower(power) == 0)
            {
                target->CastSpell(target, 32961, true, 0, this);
                // Remove aura
                GetBase()->SetDuration(0);
            }
        }
        // Drain Mana
        if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[0] & 0x00000010)
        {
            int32 manaFeedVal = 0;
            if (AuraEffect const * aurEff = GetBase()->GetEffect(1))
                manaFeedVal = aurEff->GetAmount();
            // Mana Feed - Drain Mana
            if (manaFeedVal > 0)
            {
                manaFeedVal = manaFeedVal * gain_amount / 100;
                caster->CastCustomSpell(caster, 32554, &manaFeedVal, NULL, NULL, true, NULL, this);
            }
        }
        break;
    }
    case SPELL_AURA_OBS_MOD_POWER:
    {
        if (GetMiscValue() < 0)
            return;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        Powers power;
        if (GetMiscValue() == POWER_ALL)
            power = target->getPowerType();
        else
            power = Powers(GetMiscValue());

        if (target->GetMaxPower(power) == 0)
            return;

        if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
            return;

        uint32 amount = m_amount * target->GetMaxPower(power) / 100;
        sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());

        SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
        target->SendPeriodicAuraLog(&pInfo);

        int32 gain = target->ModifyPower(power, amount);

        if (caster)
            target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
        break;
    }
    case SPELL_AURA_PERIODIC_ENERGIZE:
    {
        // ignore non positive values (can be result apply spellmods to aura damage
        if (m_amount < 0 || GetMiscValue() >= int8(MAX_POWERS))
            return;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        Powers power = Powers(GetMiscValue());

        if (target->GetMaxPower(power) == 0)
            return;

        if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
            return;

        uint32 amount = m_amount;

        SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
        target->SendPeriodicAuraLog(&pInfo);

        sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());

        int32 gain = target->ModifyPower(power, amount);

        if (caster)
            target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
        break;
    }
    case SPELL_AURA_POWER_BURN:
    {
        if (!caster)
            return;

        if (!target->isAlive())
            return;

        if (target->HasUnitState(UNIT_STAT_ISOLATED))
        {
            SendTickImmune(target, caster);
            return;
        }

        // Check for immune (not use charges)
        if (target->IsImmunedToDamage(GetSpellProto()))
        {
            SendTickImmune(target, caster);
            return;
        }

        int32 damage = m_amount > 0 ? m_amount : 0;

        Powers powerType = Powers(GetMiscValue());

        if (!target->isAlive() || target->getPowerType() != powerType)
            return;

        uint32 gain = uint32(-target->ModifyPower(powerType, -damage));

        float dmgMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);

        SpellEntry const* spellProto = GetSpellProto();
        //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
        SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask);
        //no SpellDamageBonus for burn mana
        caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);

        caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);

        caster->SendSpellNonMeleeDamageLog(&damageInfo);

        // Set trigger flag
        uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
        uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
        uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT;
        if (damageInfo.damage)
            procVictim |= PROC_FLAG_TAKEN_DAMAGE;

        caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);

        caster->DealSpellDamage(&damageInfo, true);
        break;
    }
    case SPELL_AURA_DUMMY:
        // Haunting Spirits
        if (GetId() == 7057)
            target->CastSpell((Unit *) NULL, GetAmount(), true);          // um... why?
        break;
    case SPELL_AURA_PERIODIC_DUMMY:
        PeriodicDummyTick(target, caster);
        break;
    case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
        TriggerSpell(target, caster);
        break;
    case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
        TriggerSpellWithValue(target, caster);
        break;
    default:
        break;
    }
}

void AuraEffect::PeriodicDummyTick (Unit *target, Unit *caster) const
{
    switch (GetSpellProto()->SpellFamilyName)
    {
    case SPELLFAMILY_GENERIC:
        switch (GetId())
        {
        // Forsaken Skills
        case 7054:
        {
            // Possibly need cast one of them (but
            // 7038 Forsaken Skill: Swords
            // 7039 Forsaken Skill: Axes
            // 7040 Forsaken Skill: Daggers
            // 7041 Forsaken Skill: Maces
            // 7042 Forsaken Skill: Staves
            // 7043 Forsaken Skill: Bows
            // 7044 Forsaken Skill: Guns
            // 7045 Forsaken Skill: 2H Axes
            // 7046 Forsaken Skill: 2H Maces
            // 7047 Forsaken Skill: 2H Swords
            // 7048 Forsaken Skill: Defense
            // 7049 Forsaken Skill: Fire
            // 7050 Forsaken Skill: Frost
            // 7051 Forsaken Skill: Holy
            // 7053 Forsaken Skill: Shadow
            return;
        }
        case 54798:          // FLAMING Arrow Triggered Effect
        {
            if (!target || !target->ToCreature() || !caster->IsVehicle())
                return;

            Unit *rider = caster->GetVehicleKit()->GetPassenger(0);
            if (!rider)
                return;

            // set ablaze
            if (target->HasAuraEffect(54683, EFFECT_0))
                return;
            else
                target->CastSpell(target, 54683, true);

            // Credit Frostworgs
            if (target->GetEntry() == 29358)
                rider->CastSpell(rider, 54896, true);
            // Credit Frost Giants
            else if (target->GetEntry() == 29351)
                rider->CastSpell(rider, 54893, true);

            break;
        }
        case 62292:          // Blaze (Pool of Tar)
            // should we use custom damage?
            target->CastSpell((Unit*) NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
            break;
        case 62399:          // Overload Circuit
            if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2))
            {
                target->CastSpell(target, 62475, true);          // System Shutdown
                if (Unit *veh = target->GetVehicleBase())
                    veh->CastSpell(target, 62475, true);
            }
            break;
        case 64821:          // Fuse Armor (Razorscale)
            if (GetBase()->GetStackAmount() == GetSpellProto()->StackAmount)
            {
                target->CastSpell(target, 64774, true, NULL, NULL, GetCasterGUID());
                target->RemoveAura(64821);
            }
            break;
        }
        break;
    case SPELLFAMILY_MAGE:
    {
        // Mirror Image
        if (GetId() == 55342)
            // Set name of summons to name of caster
            target->CastSpell((Unit *) NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
        break;
    }
    case SPELLFAMILY_WARLOCK:
    {
        switch (GetSpellProto()->Id)
        {
        // Demonic Circle
        case 48018:
            if (GameObject *obj = target->GetGameObject(GetSpellProto()->Id))
            {
                if (target->IsWithinDist(obj, GetSpellMaxRange(48020, true)))
                {
                     if (!target->HasAura(62388))
                        target->SendAuraVisualForSelf(true,62388, 1);
                }
                else
                    target->SendAuraVisualForSelf(false,62388);
            }
            break;
        }
        break;
    }
    case SPELLFAMILY_DRUID:
    {
        switch (GetSpellProto()->Id)
        {
        // Frenzied Regeneration
        case 22842:
        {
            // Converts up to 10 rage per second into health for $d.  Each point of rage is converted into ${$m2/10}.15% of max health.
            // Should be manauser
            if (target->getPowerType() != POWER_RAGE)
                break;
            uint32 rage = target->GetPower(POWER_RAGE);
            // Nothing todo
            if (rage == 0)
                break;
            int32 mod = (rage < 100) ? rage : 100;
            int32 points = target->CalculateSpellDamage(target, GetSpellProto(), 1);
            int32 regen = (target->GetMaxHealth() * (mod * points / 10) / 100) / 200;
            target->CastCustomSpell(target, 22845, &regen, 0, 0, true, 0, this);
            target->SetPower(POWER_RAGE, rage - mod);
            break;
        }
            // Force of Nature
        case 33831:
            break;
        }
        break;
    }
    case SPELLFAMILY_ROGUE:
    {
        switch (GetSpellProto()->Id)
        {
        // Master of Subtlety
        case 31666:
            if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
                target->RemoveAurasDueToSpell(31665);
            break;
            // Killing Spree
        case 51690:
        {
            // TODO: this should use effect[1] of 51690
            UnitList targets;
            {
                // eff_radius == 0
                float radius = GetSpellMaxRange(GetSpellProto(), false);

                CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
                Cell cell(p);
                cell.data.Part.reserved = ALL_DISTRICT;

                Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius);
                Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster, targets, u_check);

                TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer> grid_object_checker(checker);
                TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer> world_object_checker(checker);

                cell.Visit(p, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
                cell.Visit(p, world_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
            }

            if (targets.empty())
                return;

            UnitList::const_iterator itr = targets.begin();
            std::advance(itr, rand() % targets.size());
            Unit* spellTarget = *itr;

            target->CastSpell(spellTarget, 57840, true);
            target->CastSpell(spellTarget, 57841, true);
            break;
        }
            // Overkill
        case 58428:
            if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
                target->RemoveAurasDueToSpell(58427);
            break;
        }
        break;
    }
    case SPELLFAMILY_HUNTER:
    {
        // Explosive Shot
        if (GetSpellProto()->SpellFamilyFlags[1] & 0x80000000)
        {
            if (caster)
                caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, target, true, NULL, this);
            break;
        }
        switch (GetSpellProto()->Id)
        {
        // Feeding Frenzy Rank 1
        case 53511:
            if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
                target->CastSpell(target, 60096, true, 0, this);
            return;
            // Feeding Frenzy Rank 2
        case 53512:
            if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
                target->CastSpell(target, 60097, true, 0, this);
            return;
        default:
            break;
        }
        break;
    }
    case SPELLFAMILY_SHAMAN:
        if (GetId() == 52179)          // Astral Shift
        {
            // Periodic need for remove visual on stun/fear/silence lost
            if (!(target->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED | UNIT_FLAG_FLEEING | UNIT_FLAG_SILENCED)))
                target->RemoveAurasDueToSpell(52179);
            break;
        }
        break;
    case SPELLFAMILY_DEATHKNIGHT:
        switch (GetId())
        {
        case 49016:          // Hysteria
            if (target && caster && caster->IsInRaidWith(target))
            {
                if (target->GetTypeId() != TYPEID_PLAYER)
                    return;
                if (((Player*) target)->getClass() != CLASS_DEATH_KNIGHT)
                    return;
                uint32 damage = uint32(target->CountPctFromMaxHealth(1));
                target->DealDamage(target, damage, NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
            }
            break;
        }
        // Death and Decay
        if (GetSpellProto()->SpellFamilyFlags[0] & 0x20)
        {
            if (caster)
                caster->CastCustomSpell(target, 52212, &m_amount, NULL, NULL, true, 0, this);
            break;
        }
        // Blood of the North
        // Reaping
        // Death Rune Mastery
        if (GetSpellProto()->SpellIconID == 3041 || GetSpellProto()->SpellIconID == 22 || GetSpellProto()->SpellIconID == 2622)
        {
            if (target->GetTypeId() != TYPEID_PLAYER)
                return;
            if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
                return;

            // timer expired - remove death runes
            target->ToPlayer()->RemoveRunesByAuraEffect(this);
        }
        break;
    default:
        break;
    }
}

Unit* AuraEffect::GetTriggerTarget (Unit *target) const
{
    if (target->GetTypeId() == TYPEID_UNIT)
    {
        if (Unit *trigger = target->ToCreature()->AI()->GetAuraEffectTriggerTarget(GetId(), GetEffIndex()))
            return trigger;
    }
    return target;
}

void AuraEffect::TriggerSpell (Unit *target, Unit *caster) const
{
    if (!caster || !target)
        return;

    Unit* triggerTarget = GetTriggerTarget(target);

    // generic casting code with custom spells and target/caster customs
    uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[GetEffIndex()];

    SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
    SpellEntry const *auraSpellInfo = GetSpellProto();
    uint32 auraId = auraSpellInfo->Id;

    // specific code for cases with no trigger spell provided in field
    if (triggeredSpellInfo == NULL)
    {
        switch (auraSpellInfo->SpellFamilyName)
        {
        case SPELLFAMILY_GENERIC:
        {
            switch (auraId)
            {
            // Thaumaturgy Channel
            case 9712:
                triggerSpellId = 21029;
                break;
                // Brood Affliction: Bronze
            case 23170:
                triggerSpellId = 23171;
                return;
                // Restoration
            case 24379:
            case 23493:
            {
                int32 heal = caster->CountPctFromMaxHealth(10);
                caster->HealBySpell(target, auraSpellInfo, heal);

                int32 mana = caster->GetMaxPower(POWER_MANA);
                if (mana)
                {
                    mana /= 10;
                    caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA);
                }
                return;
            }
                // Nitrous Boost
            case 27746:
                if (target->GetPower(POWER_MANA) >= 10)
                {
                    target->ModifyPower(POWER_MANA, -10);
                    target->SendEnergizeSpellLog(caster, 27746, 10, POWER_MANA);
                }
                else
                    target->RemoveAurasDueToSpell(27746);
                return;
                // Frost Blast
            case 27808:
                caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, int32(target->CountPctFromMaxHealth(21)), target, true, NULL, this);
                return;
                // Detonate Mana
            case 27819:
                if (int32 mana = (int32) (target->GetMaxPower(POWER_MANA) / 10))
                {
                    mana = target->ModifyPower(POWER_MANA, -mana);
                    target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana * 10, target, true, NULL, this);
                }
                return;
                // Inoculate Nestlewood Owlkin
            case 29528:
                if (triggerTarget->GetTypeId() != TYPEID_UNIT)          // prevent error reports in case ignored player target
                    return;
                break;
                // Feed Captured Animal
            case 29917:
                triggerSpellId = 29916;
                break;
                // Extract Gas
            case 30427:
            {
                // move loot to player inventory and despawn target
                if (caster->GetTypeId() == TYPEID_PLAYER && triggerTarget->GetTypeId() == TYPEID_UNIT && triggerTarget->ToCreature()->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
                {
                    Player *player = (Player*) caster;
                    Creature *creature = triggerTarget->ToCreature();
                    // missing lootid has been reported on startup - just return
                    if (!creature->GetCreatureInfo()->SkinLootId)
                        return;

                    player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, true);

                    creature->ForcedDespawn();
                }
                return;
            }
                // Quake
            case 30576:
                triggerSpellId = 30571;
                break;
                // Doom
                // TODO: effect trigger spell may be independant on spell targets, and executed in spell finish phase
                // so instakill will be naturally done before trigger spell
            case 31347:
            {
                target->CastSpell(target, 31350, true, NULL, this);
                target->Kill(target);
                return;
            }
                // Spellcloth
            case 31373:
            {
                // Summon Elemental after create item
                target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
                return;
            }
                // Flame Quills
            case 34229:
            {
                // cast 24 spells 34269-34289, 34314-34316
                for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
                    caster->CastSpell(target, spell_id, true, NULL, this);
                for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
                    caster->CastSpell(target, spell_id, true, NULL, this);
                return;
            }
                // Remote Toy
            case 37027:
                triggerSpellId = 37029;
                break;
                // Eye of Grillok
            case 38495:
            {
                target->CastSpell(target, 38530, true, NULL, this);
                return;
            }
                // Absorb Eye of Grillok (Zezzak's Shard)
            case 38554:
            {
                if (target->GetTypeId() != TYPEID_UNIT)
                    return;

                caster->CastSpell(caster, 38495, true, NULL, this);

                Creature *creatureTarget = target->ToCreature();

                creatureTarget->ForcedDespawn();
                return;
            }
                // Tear of Azzinoth Summon Channel - it's not really supposed to do anything, and this only prevents the console spam
            case 39857:
                triggerSpellId = 39856;
                break;
                // Prismatic Shield
            case 40879:
                switch (rand() % 6)
                {
                case 0:
                    triggerSpellId = 40880;
                    break;
                case 1:
                    triggerSpellId = 40882;
                    break;
                case 2:
                    triggerSpellId = 40883;
                    break;
                case 3:
                    triggerSpellId = 40891;
                    break;
                case 4:
                    triggerSpellId = 40896;
                    break;
                case 5:
                    triggerSpellId = 40897;
                    break;
                }
                break;
                // Aura of Desire
            case 41350:
            {
                AuraEffect * aurEff = this->GetBase()->GetEffect(EFFECT_1);
                int32 amount = aurEff->GetAmount() - 5 < -100 ? -100 : aurEff->GetAmount() - 5;
                aurEff->ChangeAmount(amount, false);
                return;
            }
                // Personalized Weather
            case 46736:
                triggerSpellId = 46737;
                break;
                // Shield Level 1
            case 63130:
                // Shield Level 2
            case 63131:
                // Shield Level 3
            case 63132:
                // Ball of Flames Visual
            case 71706:
                return;
            }
            break;
        }
        case SPELLFAMILY_WARRIOR:
        {
            switch (auraId)
            {
            case 46924:          // Bladestorm
                triggerSpellId = 50622;          // Whirldwind
                return;
            }
            break;
        }
        case SPELLFAMILY_MAGE:
        {
            switch (auraId)
            {
            // Invisibility
            case 66:
                // Here need periodic triger reducing threat spell (or do it manually)
                return;
            }
            break;
        }
        case SPELLFAMILY_DRUID:
        {
            switch (auraId)
            {
            // Cat Form
            // triggerSpellId not set and unknown effect triggered in this case, ignoring for while
            case 768:
                return;
            }
            break;
        }
        case SPELLFAMILY_SHAMAN:
        {
            switch (auraId)
            {
            // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
            case 28820:
            {
                // Need remove self if Lightning Shield not active
                if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400))
                    target->RemoveAurasDueToSpell(28820);
                return;
            }
                // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
            case 38443:
            {
                bool all = true;
                for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
                {
                    if (!target->m_SummonSlot[i])
                    {
                        all = false;
                        break;
                    }
                }

                if (all)
                    caster->CastSpell(target, 38437, true, NULL, this);
                else
                    target->RemoveAurasDueToSpell(38437);
                return;
            }
            }
            break;
        }
        default:
            break;
        }
    }
    else
    {
        // Spell exist but require custom code
        switch (auraId)
        {
        case 66869:
            switch (caster->GetMap()->GetDifficulty())
            {
            case RAID_DIFFICULTY_10MAN_NORMAL:
                triggerSpellId = 66870;
                break;
            case RAID_DIFFICULTY_10MAN_HEROIC:
                triggerSpellId = 67621;
                break;
            case RAID_DIFFICULTY_25MAN_NORMAL:
                triggerSpellId = 67622;
                break;
            case RAID_DIFFICULTY_25MAN_HEROIC:
                triggerSpellId = 67623;
                break;
            }
            break;
            // Pursuing Spikes (Anub'arak)
        case 65920:
        case 65922:
        case 65923:
            if (caster->HasAura(66193))
            {
                if (Unit *permafrostCaster = caster->GetAura(66193)->GetCaster())
                    if (Creature *permafrostCasterAsCreature = permafrostCaster->ToCreature())
                        permafrostCasterAsCreature->ForcedDespawn(3000);

                caster->CastSpell(caster, 66181, false);
                caster->RemoveAllAuras();
                if (Creature *casterAsCreature = caster->ToCreature())
                    casterAsCreature->DisappearAndDie();
            }
            break;
            // Mana Tide
        case 16191:
            target->CastCustomSpell(triggerTarget, triggerSpellId, &m_amount, NULL, NULL, true, NULL, this);
            return;
            // Negative Energy Periodic
        case 46284:
            caster->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this);
            return;
            // Poison (Grobbulus)
        case 28158:
        case 54362:
            // Slime Pool (Dreadscale & Acidmaw)
        case 66882:
            target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32) ((((float) m_tickNumber / 60) * 0.9f + 0.1f) * 10000), NULL, true, NULL, this);
            return;
            // Beacon of Light
        case 53563:
        {
            Unit *triggerCaster = (Unit *) (GetBase()->GetOwner());
            triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this, triggerCaster->GetGUID());
            return;
        }
            // Rapid Recuperation (triggered energize have basepoints == 0)
        case 56654:
        case 58882:
        {
            if (int32 mana = target->GetMaxPower(POWER_FOCUS) / 100 * GetAmount())
                target->CastCustomSpell(target, triggerSpellId, &mana, NULL, NULL, true, NULL, this);
            return;
        }
            // Slime Spray - temporary here until preventing default effect works again
            // added on 9.10.2010
        case 69508:
        {
            caster->CastSpell(triggerTarget, triggerSpellId, true, NULL, NULL, caster->GetGUID());
            return;
        }
        }
    }

    // Reget trigger spell proto
    triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);

    if (triggeredSpellInfo)
    {
        Unit *triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);
        triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this);
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::TriggerSpell: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id);
    }
    else
    {
        Creature* c = triggerTarget->ToCreature();
        if (!c || (c && !sScriptMgr->OnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()), triggerTarget->ToCreature())) || (c && !c->AI()->sOnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()))))
            sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::TriggerSpell: Spell %u has value 0 in EffectTriggered[%d] and is therefor not handled. Define as custom case?", GetId(), GetEffIndex());
    }
}

void AuraEffect::TriggerSpellWithValue (Unit *target, Unit *caster) const
{
    if (!caster || !target)
        return;

    Unit* triggerTarget = GetTriggerTarget(target);

    uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[m_effIndex];
    SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
    if (triggeredSpellInfo)
    {
        Unit *triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);

        // generic casting code with custom spells and target/caster customs
        int32 basepoints0 = GetAmount();
        triggerCaster->CastCustomSpell(triggerTarget, triggerSpellId, &basepoints0, 0, 0, true, 0, this);
    }
    else
        sLog->outError("AuraEffect::TriggerSpellWithValue: Spell %u have 0 in EffectTriggered[%d], not handled custom case?", GetId(), GetEffIndex());
}

bool AuraEffect::IsAffectedOnSpell (SpellEntry const *spell) const
{
    if (!spell)
        return false;
    // Check family name
    if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
        return false;

    // Check EffectClassMask
    if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags)
        return true;
    return false;
}

void AuraEffect::CleanupTriggeredSpells (Unit *target)
{
    uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
    if (!tSpellId)
        return;

    SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
    if (!tProto)
        return;

    if (GetSpellDuration(tProto) != -1)
        return;

    // needed for spell 43680, maybe others
    // TODO: is there a spell flag, which can solve this in a more sophisticated way?
    if (m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && uint32(GetSpellDuration(m_spellProto)) == m_spellProto->EffectAmplitude[GetEffIndex()])
        return;

    target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID());
}

void AuraEffect::HandleShapeshiftBoosts (Unit *target, bool apply) const
{
    uint32 spellId = 0;
    uint32 spellId2 = 0;
    //uint32 spellId3 = 0;
    uint32 HotWSpellId = 0;

    switch (GetMiscValue())
    {
    case FORM_CAT:
        spellId = 3025;
        HotWSpellId = 24900;
        break;
    case FORM_TREE:
        spellId = 52553;
        spellId2 = 5420;
        break;
    case FORM_TRAVEL:
        spellId = 5419;
        break;
    case FORM_AQUA:
        spellId = 5421;
        break;
    case FORM_BEAR:
        spellId = 1178;
        spellId2 = 21178;
        HotWSpellId = 24899;
        break;
    case FORM_DIREBEAR:
        spellId = 9635;
        spellId2 = 21178;
        HotWSpellId = 24899;
        break;
    case FORM_BATTLESTANCE:
        spellId = 21156;
        break;
    case FORM_DEFENSIVESTANCE:
        spellId = 7376;
        break;
    case FORM_BERSERKERSTANCE:
        spellId = 7381;
        break;
    case FORM_MOONKIN:
        spellId = 24905;
        spellId2 = 69366;
        break;
    case FORM_FLIGHT:
        spellId = 33948;
        spellId2 = 34764;
        break;
    case FORM_FLIGHT_EPIC:
        spellId = 40122;
        spellId2 = 40121;
        break;
    case FORM_METAMORPHOSIS:
        spellId = 54817;
        spellId2 = 54879;
        break;
    case FORM_SPIRITOFREDEMPTION:
        spellId = 27792;
        spellId2 = 27795;          // must be second, this important at aura remove to prevent to early iterator invalidation.
        break;
    case FORM_SHADOW:
        spellId = 49868;
        spellId2 = 71167;
        break;
    case FORM_GHOSTWOLF:
        spellId = 67116;
        break;
    case FORM_GHOUL:
    case FORM_AMBIENT:
    case FORM_STEALTH:
    case FORM_CREATURECAT:
    case FORM_CREATUREBEAR:
        break;
    default:
        break;
    }

    if (apply)
    {
        // Remove cooldown of spells triggered on stance change - they may share cooldown with stance spell
        if (spellId)
        {
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->RemoveSpellCooldown(spellId);
            target->CastSpell(target, spellId, true, NULL, this);
        }

        if (spellId2)
        {
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->RemoveSpellCooldown(spellId2);
            target->CastSpell(target, spellId2, true, NULL, this);
        }

        if (target->GetTypeId() == TYPEID_PLAYER)
        {
            const PlayerSpellMap& sp_list = target->ToPlayer()->GetSpellMap();
            for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
            {
                if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
                    continue;
                if (itr->first == spellId || itr->first == spellId2)
                    continue;
                SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
                if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | (1 << 7))))
                    continue;
                if (spellInfo->Stances & (1 << (GetMiscValue() - 1)))
                    target->CastSpell(target, itr->first, true, NULL, this);
            }
            // Leader of the Pack
            if (target->ToPlayer()->HasSpell(17007))
            {
                SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
                if (spellInfo && spellInfo->Stances & (1 << (GetMiscValue() - 1)))
                    target->CastSpell(target, 24932, true, NULL, this);
            }
            // Improved Barkskin - apply/remove armor bonus due to shapeshift
            if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
            {
                target->RemoveAurasDueToSpell(66530);
                if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE)          // "while in Travel Form or while not shapeshifted"
                    target->CastSpell(target, 66530, true);
            }
            // Heart of the Wild
            if (HotWSpellId)
            {          // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
                Unit::AuraEffectList const& mModTotalStatPct = target->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
                for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
                {
                    // Heart of the Wild
                    if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetMiscValue() == 3)
                    {
                        int32 HotWMod = (*i)->GetAmount();

                        target->CastCustomSpell(target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
                        break;
                    }
                }
            }
            switch (GetMiscValue())
            {
            case FORM_CAT:
                // Savage Roar
                if (target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0, 0x10000000, 0))
                    target->CastSpell(target, 62071, true);
                // Nurturing Instinct
                if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254, 0))
                {
                    uint32 spellId = 0;
                    switch (aurEff->GetId())
                    {
                    case 33872:
                        spellId = 47179;
                        break;
                    case 33873:
                        spellId = 47180;
                        break;
                    }
                    target->CastSpell(target, spellId, true, NULL, this);
                }
                // Master Shapeshifter - Cat
                if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, 0))
                {
                    if (target->HasAura(48418))
                        target->RemoveAurasDueToSpell(48418);
                    int32 bp = aurEff->GetAmount();
                    target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true);
                }
                break;
            case FORM_DIREBEAR:
            case FORM_BEAR:
                // Master Shapeshifter - Bear
                if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, 0))
                {
                    int32 bp = aurEff->GetAmount();
                    target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true);
                }
                // Survival of the Fittest
                if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0))
                {
                    int32 bp = 100 + SpellMgr::CalculateSpellEffectAmount(aurEff->GetSpellProto(), 2);
                    target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this);
                }
                break;
            case FORM_MOONKIN:
                // Master Shapeshifter - Moonkin
                if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, 0))
                {
                    if (target->HasAura(48418))
                        target->RemoveAurasDueToSpell(48418);
                    int32 bp = aurEff->GetAmount();
                    target->CastCustomSpell(target, 48421, &bp, NULL, NULL, true);
                }
                break;
            }
        }
    }
    else
    {
        if (spellId)
            target->RemoveAurasDueToSpell(spellId);
        if (spellId2)
            target->RemoveAurasDueToSpell(spellId2);

        // Improved Barkskin - apply/remove armor bonus due to shapeshift
        if (Player *pl = target->ToPlayer())
        {
            if (pl->HasSpell(63410) || pl->HasSpell(63411))
            {
                target->RemoveAurasDueToSpell(66530);
                target->CastSpell(target, 66530, true);
            }
        }

        Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
        for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
        {
            if (itr->second->GetBase()->IsRemovedOnShapeLost(target))
                target->RemoveAura(itr);
            else
                ++itr;
        }
    }
}

/*********************************************************/
/***               AURA EFFECT HANDLERS                ***/
/*********************************************************/

/**************************************/
/***       VISIBILITY & PHASES      ***/
/**************************************/

void AuraEffect::HandleModInvisibilityDetect (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();
    InvisibilityType type = InvisibilityType(GetMiscValue());

    if (apply)
    {
        target->m_invisibilityDetect.AddFlag(type);
        target->m_invisibilityDetect.AddValue(type, GetAmount());
    }
    else
    {
        if (!target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY_DETECT))
            target->m_invisibilityDetect.DelFlag(type);

        target->m_invisibilityDetect.AddValue(type, -GetAmount());
    }

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleModInvisibility (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();
    InvisibilityType type = InvisibilityType(GetMiscValue());

    if (apply)
    {
        // drop flag at invisibiliy in bg
        if (mode & AURA_EFFECT_HANDLE_REAL)
            target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);

        // apply glow vision
        if (target->GetTypeId() == TYPEID_PLAYER)
            target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);

        target->m_invisibility.AddFlag(type);
        target->m_invisibility.AddValue(type, GetAmount());
    }
    else
    {
        if (!target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
        {
            // if not have different invisibility auras.
            // remove glow vision
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->RemoveByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);

            target->m_invisibility.DelFlag(type);
        }

        target->m_invisibility.AddValue(type, -GetAmount());
    }

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleModStealthDetect (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit * target = aurApp->GetTarget();
    StealthType type = StealthType(GetMiscValue());

    if (apply)
    {
        target->m_stealthDetect.AddFlag(type);
        target->m_stealthDetect.AddValue(type, GetAmount());
    }
    else
    {
        if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH_DETECT))
            target->m_stealthDetect.DelFlag(type);

        target->m_stealthDetect.AddValue(type, -GetAmount());
    }

    target->UpdateObjectVisibility();
}
//trap launcher aura. Need cast or add spell on AB. need more ways for continues
void AuraEffect::HandleModTrapLauncher (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;
    Unit *target = aurApp->GetTarget();
}
//TODO: Thats way? (for guild bonus spell)
void AuraEffect::HandleAuraSaleForGuild (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
}

//TODO: Finish this aura
void AuraEffect::HandleModCamouflage (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        target->CastSpell(target, 80326, true);
    }
    else if (!(target->isCamouflaged()))
    {
        target->RemoveAura(80326);
        target->RemoveAura(80325);
    }
}

void AuraEffect::HandleModStealth (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();
    StealthType type = StealthType(GetMiscValue());

    if (apply)
    {
        if (mode & AURA_EFFECT_HANDLE_REAL)
        {
            // drop flag at stealth in bg
            target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
        }

        target->m_stealth.AddFlag(type);
        target->m_stealth.AddValue(type, GetAmount());

        target->SetStandFlags(UNIT_STAND_FLAGS_CREEP);
        if (target->GetTypeId() == TYPEID_PLAYER)
            target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_STEALTH);
    }
    else
    {
        if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))          // if last SPELL_AURA_MOD_STEALTH
        {
            target->m_stealth.DelFlag(type);

            target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
        }
    }

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleModStealthLevel (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit * target = aurApp->GetTarget();
    StealthType type = StealthType(GetMiscValue());

    if (apply)
        target->m_stealth.AddValue(type, GetAmount());
    else
        target->m_stealth.AddValue(type, -GetAmount());

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleSpiritOfRedemption (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // prepare spirit state
    if (apply)
    {
        if (target->GetTypeId() == TYPEID_PLAYER)
        {
            // disable breath/etc timers
            target->ToPlayer()->StopMirrorTimers();

            // set stand state (expected in this form)
            if (!target->IsStandState())
                target->SetStandState(UNIT_STAND_STATE_STAND);
        }

        target->SetHealth(1);
    }
    // die at aura end
    else
        target->setDeathState(JUST_DIED);
}

void AuraEffect::HandleAuraGhost (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    if (apply)
    {
        target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
        target->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
        target->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
    }
    else
    {
        if (target->HasAuraType(SPELL_AURA_GHOST))
            return;

        target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
        target->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
        target->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
    }
}

void AuraEffect::HandlePhase (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    // MiscValue is PhaseMask
    // MiscValueB is PhaseID (from Phase.dbc)
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    // no-phase is also phase state so same code for apply and remove
    uint32 newPhase = 0;
    Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
    if (!phases.empty())
        for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
            newPhase |= (*itr)->GetMiscValue();

    // phase auras normally not expected at BG but anyway better check
    if (Player* player = target->ToPlayer())
    {
        if (!newPhase)
            newPhase = PHASEMASK_NORMAL;

        // drop flag at invisible in bg
        if (player->InBattleground())
            if (Battleground *bg = player->GetBattleground())
                bg->EventPlayerDroppedFlag(player);

        // stop handling the effect if it was removed by linked event
        if (apply && aurApp->GetRemoveMode())
            return;

        // GM-mode have mask 0xFFFFFFFF
        if (player->isGameMaster())
            newPhase = 0xFFFFFFFF;

        player->SetPhaseMask(newPhase, false);
        player->GetSession()->SendSetPhaseShift(newPhase);
    }
    else
    {
        if (!newPhase)
        {
            newPhase = PHASEMASK_NORMAL;
            if (Creature* creature = target->ToCreature())
                if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetDBTableGUIDLow()))
                    newPhase = data->phaseMask;
        }

        target->SetPhaseMask(newPhase, false);
    }

    // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
    if (target->IsVisible())
        target->UpdateObjectVisibility();
}

/**********************/
/***   UNIT MODEL   ***/
/**********************/

void AuraEffect::HandleAuraModShapeshift (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    uint32 modelid = 0;
    Powers PowerType = POWER_MANA;
    ShapeshiftForm form = ShapeshiftForm(GetMiscValue());

    switch (form)
    {
    case FORM_CAT:
    case FORM_GHOUL:
        PowerType = POWER_ENERGY;
        break;
    case FORM_BEAR:
    case FORM_DIREBEAR:
    case FORM_BATTLESTANCE:
    case FORM_BERSERKERSTANCE:
    case FORM_DEFENSIVESTANCE:
        PowerType = POWER_RAGE;
        break;
    case FORM_TRAVEL:
    case FORM_AQUA:
    case FORM_CREATUREBEAR:
    case FORM_GHOSTWOLF:
    case FORM_FLIGHT:
    case FORM_MOONKIN:
    case FORM_FLIGHT_EPIC:
    case FORM_METAMORPHOSIS:
    case FORM_MASTER_ANGLER:
    case FORM_AMBIENT:
    case FORM_SHADOW:
    case FORM_STEALTH:
    case FORM_UNDEAD:
    case FORM_SHADOW_DANCE:
    case FORM_TREE:
    case FORM_SPIRITOFREDEMPTION:
        break;
    default:
        sLog->outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue());
    }

    modelid = target->GetModelForForm(form);

    if (apply)
    {
        // remove polymorph before changing display id to keep new display id
        switch (form)
        {
        case FORM_CAT:
        case FORM_TREE:
        case FORM_TRAVEL:
        case FORM_AQUA:
        case FORM_BEAR:
        case FORM_DIREBEAR:
        case FORM_FLIGHT_EPIC:
        case FORM_FLIGHT:
        case FORM_MOONKIN:
        {
            // remove movement affects without root
            target->RemoveAurasWithMechanic((1 << MECHANIC_SNARE));

            // and polymorphic affects
            if (target->IsPolymorphed())
                target->RemoveAurasDueToSpell(target->getTransForm());
            break;
        }
        default:
            break;
        }

        // remove other shapeshift before applying a new one
        target->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT, 0, GetBase());

        // stop handling the effect if it was removed by linked event
        if (aurApp->GetRemoveMode())
            return;

        if (modelid > 0)
            target->SetDisplayId(modelid);

        if (PowerType != POWER_MANA)
        {
            uint32 oldPower = target->GetPower(PowerType);
            // reset power to default values only at power change
            if (target->getPowerType() != PowerType)
                target->setPowerType(PowerType);

            switch (form)
            {
            case FORM_CAT:
            case FORM_BEAR:
            case FORM_DIREBEAR:
            {
                // get furor proc chance
                uint32 FurorChance = 0;
                if (AuraEffect const *dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0))
                    FurorChance = std::max(dummy->GetAmount(), 0);

                switch (GetMiscValue())
                {
                case FORM_CAT:
                {
                    int32 basePoints = int32(std::min(oldPower, FurorChance));
                    target->SetPower(POWER_ENERGY, 0);
                    target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
                }
                    break;
                case FORM_BEAR:
                case FORM_DIREBEAR:
                    if (urand(0, 99) < FurorChance)
                        target->CastSpell(target, 17057, true);
                default:
                {
                    uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance);
                    target->SetPower(POWER_ENERGY, newEnergy);
                }
                    break;
                }
                break;
            }
            default:
                break;
            }
        }
        // stop handling the effect if it was removed by linked event
        if (aurApp->GetRemoveMode())
            return;

        target->SetShapeshiftForm(form);
    }
    else
    {
        // reset model id if no other auras present
        // may happen when aura is applied on linked event on aura removal
        if (!target->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
        {
            target->SetShapeshiftForm(FORM_NONE);
            if (target->getClass() == CLASS_DRUID)
            {
                target->setPowerType(POWER_MANA);
                // Remove movement impairing effects(without root 4.0.6) also when shifting out
                target->RemoveAurasWithMechanic((1 << MECHANIC_SNARE));
            }
        }

        if (modelid > 0)
            target->RestoreDisplayId();

        switch (form)
        {
        // Nordrassil Harness - bonus
        case FORM_BEAR:
        case FORM_DIREBEAR:
        case FORM_CAT:
            if (AuraEffect *dummy = target->GetAuraEffect(37315, 0))
                target->CastSpell(target, 37316, true, NULL, dummy);
            break;
            // Nordrassil Regalia - bonus
        case FORM_MOONKIN:
            if (AuraEffect *dummy = target->GetAuraEffect(37324, 0))
                target->CastSpell(target, 37325, true, NULL, dummy);
            break;
        case FORM_BATTLESTANCE:
        case FORM_DEFENSIVESTANCE:
        case FORM_BERSERKERSTANCE:
        {
            uint32 Rage_val = 0;
            // Defensive Tactics
            if (form == FORM_DEFENSIVESTANCE)
            {
                if (AuraEffect const * aurEff = target->IsScriptOverriden(m_spellProto, 831))
                    Rage_val += aurEff->GetAmount() * 10;
            }
            // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
            if (target->GetTypeId() == TYPEID_PLAYER)
            {
                PlayerSpellMap const& sp_list = target->ToPlayer()->GetSpellMap();
                for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
                {
                    if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
                        continue;
                    SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
                    if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
                        Rage_val += target->CalculateSpellDamage(target, spellInfo, 0) * 10;
                }
            }
            if (target->GetPower(POWER_RAGE) > Rage_val)
                target->SetPower(POWER_RAGE, Rage_val);
            break;
        }
        default:
            break;
        }
    }

    // adding/removing linked auras
    // add/remove the shapeshift aura's boosts
    HandleShapeshiftBoosts(target, apply);

    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->InitDataForForm();

    if (target->getClass() == CLASS_DRUID)
    {
        // Dash
        if (AuraEffect * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8))
            aurEff->RecalculateAmount();

        // Disarm handling
        // If druid shifts while being disarmed we need to deal with that since forms aren't affected by disarm
        // and also HandleAuraModDisarm is not triggered
        if (!target->CanUseAttackType(BASE_ATTACK))
        {
            if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
            {
                target->ToPlayer()->_ApplyWeaponDamage(EQUIPMENT_SLOT_MAINHAND, pItem->GetProto(), NULL, apply);
            }
        }
    }

    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        SpellShapeshiftFormEntry const *shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
        // Learn spells for shapeshift form - no need to send action bars or add spells to spellbook
        for (uint8 i = 0; i < MAX_SHAPESHIFT_SPELLS; ++i)
        {
            if (!shapeInfo->stanceSpell[i])
                continue;
            if (apply)
                target->ToPlayer()->AddTemporarySpell(shapeInfo->stanceSpell[i]);
            else
                target->ToPlayer()->RemoveTemporarySpell(shapeInfo->stanceSpell[i]);
        }
    }
}

void AuraEffect::HandleAuraTransform (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case
        if (!target->GetModelForForm(target->GetShapeshiftForm()) || !IsPositiveSpell(GetId()))
        {
            // special case (spell specific functionality)
            if (GetMiscValue() == 0)
            {
                switch (GetId())
                {
                // Orb of Deception
                case 16739:
                {
                    uint32 orb_model = target->GetNativeDisplayId();
                    switch (orb_model)
                    {
                    // Troll Female
                    case 1479:
                        target->SetDisplayId(10134);
                        break;
                        // Troll Male
                    case 1478:
                        target->SetDisplayId(10135);
                        break;
                        // Tauren Male
                    case 59:
                        target->SetDisplayId(10136);
                        break;
                        // Human Male
                    case 49:
                        target->SetDisplayId(10137);
                        break;
                        // Human Female
                    case 50:
                        target->SetDisplayId(10138);
                        break;
                        // Orc Male
                    case 51:
                        target->SetDisplayId(10139);
                        break;
                        // Orc Female
                    case 52:
                        target->SetDisplayId(10140);
                        break;
                        // Dwarf Male
                    case 53:
                        target->SetDisplayId(10141);
                        break;
                        // Dwarf Female
                    case 54:
                        target->SetDisplayId(10142);
                        break;
                        // NightElf Male
                    case 55:
                        target->SetDisplayId(10143);
                        break;
                        // NightElf Female
                    case 56:
                        target->SetDisplayId(10144);
                        break;
                        // Undead Female
                    case 58:
                        target->SetDisplayId(10145);
                        break;
                        // Undead Male
                    case 57:
                        target->SetDisplayId(10146);
                        break;
                        // Tauren Female
                    case 60:
                        target->SetDisplayId(10147);
                        break;
                        // Gnome Male
                    case 1563:
                        target->SetDisplayId(10148);
                        break;
                        // Gnome Female
                    case 1564:
                        target->SetDisplayId(10149);
                        break;
                        // BloodElf Female
                    case 15475:
                        target->SetDisplayId(17830);
                        break;
                        // BloodElf Male
                    case 15476:
                        target->SetDisplayId(17829);
                        break;
                        // Dranei Female
                    case 16126:
                        target->SetDisplayId(17828);
                        break;
                        // Dranei Male
                    case 16125:
                        target->SetDisplayId(17827);
                        break;
                        // Worgen Female
                    case 29423:
                        target->SetDisplayId(30114);
                        break;
                        // Worgen Male
                    case 29422:
                        target->SetDisplayId(29335);
                        break;
                        // Goblin Female
                    case 6895:
                        target->SetDisplayId(33613);
                        break;
                        // Goblin Male
                    case 6894:
                        target->SetDisplayId(33611);
                        break;
                    default:
                        break;
                    }
                    break;
                }
                    // Murloc costume
                case 42365:
                    target->SetDisplayId(21723);
                    break;
                    // Pygmy Oil
                case 53806:
                    target->SetDisplayId(22512);
                    break;
                default:
                    break;
                }
            }
            else
            {
                CreatureInfo const * ci = ObjectMgr::GetCreatureTemplate(GetMiscValue());
                if (!ci)
                {
                    target->SetDisplayId(16358);          // pig pink ^_^
                    sLog->outError("Auras: unknown creature id = %d (only need its modelid) From Spell Aura Transform in Spell ID = %d", GetMiscValue(), GetId());
                }
                else
                {
                    uint32 model_id = 0;

                    if (uint32 modelid = ci->GetRandomValidModelId())
                        model_id = modelid;          // Will use the default model here

                    // Polymorph (sheep)
                    if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellIconID == 82 && GetSpellProto()->SpellVisual[0] == 12978)
                        if (Unit *caster = GetCaster())
                            if (caster->HasAura(52648))          // Glyph of the Penguin
                                model_id = 26452;
                            else if (caster->HasAura(57927))          // Glyph of the Monkey
                                model_id = 21362;

                    target->SetDisplayId(model_id);

                    // Dragonmaw Illusion (set mount model also)
                    if (GetId() == 42016 && target->GetMountID() && !target->GetAuraEffectsByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED).empty())
                        target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 16314);
                }
            }
        }

        // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case
        if (!target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(target->getTransForm()))
            target->setTransForm(GetId());

        // polymorph case
        if ((mode & AURA_EFFECT_HANDLE_REAL) && target->GetTypeId() == TYPEID_PLAYER && target->IsPolymorphed())
        {
            // for players, start regeneration after 1s (in polymorph fast regeneration case)
            // only if caster is Player (after patch 2.4.2)
            if (IS_PLAYER_GUID(GetCasterGUID()))
                target->ToPlayer()->setRegenTimerCount(1 * IN_MILLISECONDS);

            //dismount polymorphed target (after patch 2.4.2)
            if (target->IsMounted())
                target->RemoveAurasByType(SPELL_AURA_MOUNTED);
        }
    }
    else
    {
        // HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true) will reapply it if need
        if (target->getTransForm() == GetId())
            target->setTransForm(0);

        target->RestoreDisplayId();

        // Dragonmaw Illusion (restore mount model)
        if (GetId() == 42016 && target->GetMountID() == 16314)
        {
            if (!target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).empty())
            {
                uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue();
                if (CreatureInfo const* ci = ObjectMgr::GetCreatureTemplate(cr_id))
                {
                    uint32 team = 0;
                    if (target->GetTypeId() == TYPEID_PLAYER)
                        team = target->ToPlayer()->GetTeam();

                    uint32 display_id = sObjectMgr->ChooseDisplayId(team, ci);
                    CreatureModelInfo const *minfo = sObjectMgr->GetCreatureModelRandomGender(display_id);
                    if (minfo)
                        display_id = minfo->modelid;

                    target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, display_id);
                }
            }
        }
    }
}

void AuraEffect::HandleAuraModScale (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X, (float) GetAmount(), apply);
}

void AuraEffect::HandleAuraCloneCaster (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        Unit *caster = GetCaster();
        if (!caster)
            return;

        // Set display id (probably for portrait?)
        target->SetDisplayId(caster->GetDisplayId());
        target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE);
    }
    else
    {
        target->SetDisplayId(target->GetNativeDisplayId());
        target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE);
    }
}

/************************/
/***      FIGHT       ***/
/************************/

void AuraEffect::HandleFeignDeath (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    if (apply)
    {
        UnitList targets;
        Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetMap()->GetVisibilityRange());
        Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check);
        target->VisitNearbyObject(target->GetMap()->GetVisibilityRange(), searcher);
        for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
        {
            if (!(*iter)->HasUnitState(UNIT_STAT_CASTING))
                continue;

            for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
                if ((*iter)->GetCurrentSpell(i) && (*iter)->GetCurrentSpell(i)->m_targets.getUnitTargetGUID() == target->GetGUID())
                    (*iter)->InterruptSpell(CurrentSpellTypes(i), false);
        }
        target->CombatStop();
        target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);

        // prevent interrupt message
        if (GetCasterGUID() == target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
            target->FinishSpell(CURRENT_GENERIC_SPELL, false);
        target->InterruptNonMeleeSpells(true);
        target->getHostileRefManager().deleteReferences();

        // stop handling the effect if it was removed by linked event
        if (aurApp->GetRemoveMode())
            return;
        // blizz like 2.0.x
        target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
        // blizz like 2.0.x
        target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
        // blizz like 2.0.x
        target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);

        target->AddUnitState(UNIT_STAT_DIED);
    }
    else
    {
        target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
        target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
        target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
        target->ClearUnitState(UNIT_STAT_DIED);
    }
}

void AuraEffect::HandleModUnattackable (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        if (mode & AURA_EFFECT_HANDLE_REAL)
        {
            target->CombatStop();
            target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
        }
        // stop handling the effect if it was removed by linked event
        if (aurApp->GetRemoveMode())
            return;
    }
    // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
    else if (target->HasAuraType(SPELL_AURA_MOD_UNATTACKABLE))
        return;

    target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, apply);
}

void AuraEffect::HandleAuraModDisarm (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    AuraType type = GetAuraType();

    //Prevent handling aura twice
    if (apply ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
        return;

    uint32 field, flag, slot;
    WeaponAttackType attType;
    switch (type)
    {
    case SPELL_AURA_MOD_DISARM:
        field = UNIT_FIELD_FLAGS;
        flag = UNIT_FLAG_DISARMED;
        slot = EQUIPMENT_SLOT_MAINHAND;
        attType = BASE_ATTACK;
        break;
    case SPELL_AURA_MOD_DISARM_OFFHAND:
        field = UNIT_FIELD_FLAGS_2;
        flag = UNIT_FLAG2_DISARM_OFFHAND;
        slot = EQUIPMENT_SLOT_OFFHAND;
        attType = OFF_ATTACK;
        break;
    case SPELL_AURA_MOD_DISARM_RANGED:
        field = UNIT_FIELD_FLAGS_2;
        flag = UNIT_FLAG2_DISARM_RANGED;
        slot = EQUIPMENT_SLOT_RANGED;
        attType = RANGED_ATTACK;
        break;
    default:
        return;
    }

    if (!apply)
        target->RemoveFlag(field, flag);

    if (apply)
        target->SetFlag(field, flag);

    // Handle damage modifcation, shapeshifted druids are not affected
    if (target->GetTypeId() == TYPEID_PLAYER && !target->IsInFeralForm())
    {
        if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
        {
            uint8 attacktype = Player::GetAttackBySlot(slot);

            if (attacktype < MAX_ATTACK)
                target->ToPlayer()->_ApplyWeaponDamage(slot, pItem->GetProto(), NULL, !apply);
        }
    }

    if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->GetCurrentEquipmentId())
        target->UpdateDamagePhysical(attType);
}

void AuraEffect::HandleAuraModSilence (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
        // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
        for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
            if (Spell *spell = target->GetCurrentSpell(CurrentSpellTypes(i)))
                if (spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
                    // Stop spells on prepare or casting state
                    target->InterruptSpell(CurrentSpellTypes(i), false);
    }
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(SPELL_AURA_MOD_SILENCE) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
            return;

        target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
    }
}

void AuraEffect::HandleAuraModPacify (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
        target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(SPELL_AURA_MOD_PACIFY) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
            return;
        target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
    }
}

void AuraEffect::HandleAuraModPacifyAndSilence (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    // Vengeance of the Blue Flight (TODO: REMOVE THIS!)
    if (m_spellProto->Id == 45839)
    {
        if (apply)
            target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
        else
            target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
    }

    if (!apply)
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
            return;
    }

    HandleAuraModPacify(aurApp, mode, apply);
    HandleAuraModSilence(aurApp, mode, apply);
}

void AuraEffect::HandleAuraAllowOnlyAbility (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        if (apply)
            target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY);
        else
        {
            // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
            if (target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY))
                return;
            target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY);
        }
    }
}

/****************************/
/***      TRACKING        ***/
/****************************/

void AuraEffect::HandleAuraTrackCreatures (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->SetUInt32Value(PLAYER_TRACK_CREATURES, (apply) ? ((uint32) 1) << (GetMiscValue() - 1) : 0);
}

void AuraEffect::HandleAuraTrackResources (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->SetUInt32Value(PLAYER_TRACK_RESOURCES, (apply) ? ((uint32) 1) << (GetMiscValue() - 1) : 0);
}

void AuraEffect::HandleAuraTrackStealthed (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    if (!apply)
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
    }
    target->ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_TRACK_STEALTHED, apply);
}

void AuraEffect::HandleAuraModStalked (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
    if (apply)
        target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (!target->HasAuraType(GetAuraType()))
            target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
    }

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleAuraUntrackable (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
        target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
        target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
    }
}

/****************************/
/***  SKILLS & TALENTS    ***/
/****************************/

void AuraEffect::HandleAuraModPetTalentsPoints (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Recalculate pet talent points
    if (Pet *pet = target->ToPlayer()->GetPet())
        pet->InitTalentForLevel();
}

void AuraEffect::HandleAuraModSkill (AuraApplication const *aurApp, uint8 /*mode*/, bool apply) const
{
    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    uint32 prot = GetMiscValue();
    int32 points = GetAmount();

    target->ToPlayer()->ModifySkillBonus(prot, ((apply) ? points : -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
    if (prot == SKILL_DEFENSE)
        target->ToPlayer()->UpdateDefenseBonusesMod();
}

/****************************/
/***       MOVEMENT       ***/
/****************************/

void AuraEffect::HandleAuraMounted (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();
    uint32 spellId = (uint32) GetAmount();
    Player *plr = target->ToPlayer();
    
    switch (GetId())
    {
        case 55164: // Spectral Gryphon
            spellId = 86460;
            break;
        case 64731: // Sea Turtle
            spellId = 83159;
            break;
        default:
            break;
    }    
    
    if (plr && spellId < 2)
    {
        return;
    }
    
    if (apply)
    {
        uint32 creatureEntry = GetMiscValue();

        if (aurApp->GetBase()->GetId() == 87840)
        {
            target->Mount(plr->getGender() == GENDER_FEMALE ? 29423 : 29422, 0, GetMiscValue());
            target->Mount(plr->getGender() == GENDER_MALE ? 29422 : 29423, 0, GetMiscValue());
            return;
        }

        // Festive Holiday Mount
        if (target->HasAura(62061))
        {
            if (GetBase()->HasEffectType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
                creatureEntry = 24906;
            else
                creatureEntry = 15665;
        }

        CreatureInfo const* ci = ObjectMgr::GetCreatureTemplate(creatureEntry);
        if (!ci)
        {
            sLog->outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", GetMiscValue());
            return;
        }

        uint32 team = 0;
        if (target->GetTypeId() == TYPEID_PLAYER)
            team = target->ToPlayer()->GetTeam();

        uint32 display_id = sObjectMgr->ChooseDisplayId(team, ci);
        CreatureModelInfo const *minfo = sObjectMgr->GetCreatureModelRandomGender(display_id);
        if (minfo)
            display_id = minfo->modelid;

        //some spell has one aura of mount and one of vehicle
        for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
            if (GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON && GetSpellProto()->EffectMiscValue[i] == GetMiscValue())
                display_id = 0;

        target->Mount(display_id, ci->VehicleId, GetMiscValue());

        if (plr)
            plr->CastSpell(plr, spellId, true);
    }
    else
    {
        target->Unmount();
        if (plr)
            plr->RemoveAurasDueToSpell(spellId);
        //some mounts like Headless Horseman's Mount or broom stick are skill based spell
        // need to remove ALL arura related to mounts, this will stop client crash with broom stick
        // and never endless flying after using Headless Horseman's Mount
        if (mode & AURA_EFFECT_HANDLE_REAL)
            target->RemoveAurasByType(SPELL_AURA_MOUNTED);
    }
}

void AuraEffect::HandleAuraAllowFlight (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (!apply)
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()) || target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
            return;
    }

    if (target->GetTypeId() == TYPEID_UNIT)
        target->SetFlying(apply);

    if (Player *plr = target->m_movedPlayer)
    {
        // allow flying
        WorldPacket data;
        if (apply)
            data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12, true);
        else
            data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12, true);
        data.append(target->GetPackGUID());
        data << uint32(0);          // unk
        plr->SendDirectMessage(&data);
    }
}

void AuraEffect::HandleAuraWaterWalk (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (!(apply))
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
    }

    WorldPacket data;
    if (apply)
        data.Initialize(SMSG_MOVE_WATER_WALK, 8 + 4, true);
    else
        data.Initialize(SMSG_MOVE_LAND_WALK, 8 + 4, true);
    data.append(target->GetPackGUID());
    data << uint32(0);
    target->SendMessageToSet(&data, true);
}

void AuraEffect::HandleAuraFeatherFall (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (!(apply))
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
    }

    WorldPacket data;
    if (apply)
        data.Initialize(SMSG_MOVE_FEATHER_FALL, 8 + 4, true);
    else
        data.Initialize(SMSG_MOVE_NORMAL_FALL, 8 + 4, true);
    data.append(target->GetPackGUID());
    data << uint32(0);
    target->SendMessageToSet(&data, true);

    // start fall from current height
    if (!apply && target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->SetFallInformation(0, target->GetPositionZ());
}

void AuraEffect::HandleAuraHover (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (!apply)
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
    }

    WorldPacket data;
    if (apply)
        data.Initialize(SMSG_MOVE_SET_HOVER, 8 + 4, true);
    else
        data.Initialize(SMSG_MOVE_UNSET_HOVER, 8 + 4, true);
    data.append(target->GetPackGUID());
    data << uint32(0);
    target->SendMessageToSet(&data, true);
}

void AuraEffect::HandleWaterBreathing (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    // update timers in client
    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->UpdateMirrorTimers();
}

void AuraEffect::HandleForceMoveForward (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
        target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
        target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
    }
}

/****************************/
/***        THREAT        ***/
/****************************/

void AuraEffect::HandleModThreat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();
    for (int32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
        if (GetMiscValue() & (1 << i))
            ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModTotalThreat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (!target->isAlive() || target->GetTypeId() != TYPEID_PLAYER)
        return;

    Unit *caster = GetCaster();
    if (!caster || !caster->isAlive())
        return;

    target->getHostileRefManager().addTempThreat((float) GetAmount(), apply);
}

void AuraEffect::HandleModTaunt (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (!target->isAlive() || !target->CanHaveThreatList())
        return;

    Unit *caster = GetCaster();
    if (!caster || !caster->isAlive())
        return;

    if (apply)
        target->TauntApply(caster);
    else
    {
        // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
        target->TauntFadeOut(caster);
    }
}

/*****************************/
/***        CONTROL        ***/
/*****************************/

void AuraEffect::HandleModConfuse (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->SetControlled(apply, UNIT_STAT_CONFUSED);
}

void AuraEffect::HandleModFear (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->SetControlled(apply, UNIT_STAT_FLEEING);
}

void AuraEffect::HandleAuraModStun (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->SetControlled(apply, UNIT_STAT_STUNNED);
}

void AuraEffect::HandleAuraModRoot (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->SetControlled(apply, UNIT_STAT_ROOT);

    if (apply)
    {
        switch (GetSpellProto()->Id)
        {
        case 69001:          //Transform: Worgen. not used?
        {
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->setInWorgenForm();
            break;
        }
        default:
            break;
        }
    }
}

void AuraEffect::HandlePreventFleeing (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    Unit::AuraEffectList const& fearAuras = target->GetAuraEffectsByType(SPELL_AURA_MOD_FEAR);
    if (!fearAuras.empty())
        target->SetControlled(!(apply), UNIT_STAT_FLEEING);
}

/***************************/
/***        CHARM        ***/
/***************************/

void AuraEffect::HandleModPossess (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    Unit *caster = GetCaster();
    if (caster && caster->GetTypeId() == TYPEID_UNIT)
    {
        HandleModCharm(aurApp, mode, apply);
        return;
    }

    if (apply)
        target->SetCharmedBy(caster, CHARM_TYPE_POSSESS, aurApp);
    else
        target->RemoveCharmedBy(caster);
}

// only one spell has this aura
void AuraEffect::HandleModPossessPet (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit* caster = GetCaster();
    if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
        return;

    Unit *target = aurApp->GetTarget();
    if (target->GetTypeId() != TYPEID_UNIT || !target->ToCreature()->isPet())
        return;

    Pet* pet = target->ToPet();

    if (apply)
    {
        if (caster->ToPlayer()->GetPet() != pet)
            return;

        pet->SetCharmedBy(caster, CHARM_TYPE_POSSESS, aurApp);
    }
    else
    {
        pet->RemoveCharmedBy(caster);

        if (!pet->IsWithinDistInMap(caster, pet->GetMap()->GetVisibilityRange()))
            pet->Remove(PET_SLOT_OTHER_PET, true);
        else
        {
            // Reinitialize the pet bar and make the pet come back to the owner
            caster->ToPlayer()->PetSpellInitialize();
            if (!pet->getVictim())
                pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, pet->GetFollowAngle());
        }
    }
}

void AuraEffect::HandleModCharm (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    Unit *caster = GetCaster();

    if (apply)
        target->SetCharmedBy(caster, CHARM_TYPE_CHARM, aurApp);
    else
        target->RemoveCharmedBy(caster);
}

void AuraEffect::HandleCharmConvert (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    Unit *caster = GetCaster();

    if (apply)
        target->SetCharmedBy(caster, CHARM_TYPE_CONVERT, aurApp);
    else
        target->RemoveCharmedBy(caster);
}

void AuraEffect::HandleAuraControlVehicle (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (!target->IsVehicle())
        return;

    Unit *caster = GetCaster();

    if (!caster || caster == target)
        return;

    if (apply)
    {
        caster->EnterVehicle(target->GetVehicleKit(), m_amount - 1, true);
    }
    else
    {
        if (GetId() == 53111)          // Devour Humanoid
        {
            target->Kill(caster);
            if (caster->GetTypeId() == TYPEID_UNIT)
                caster->ToCreature()->RemoveCorpse();
        }

        // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
        caster->RemoveAurasDueToSpell(GetId());
        caster->ExitVehicle();
    }
}

/*********************************************************/
/***                  MODIFY SPEED                     ***/
/*********************************************************/
void AuraEffect::HandleAuraModIncreaseSpeed (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    // Spirit walk removes imparing effects
    if (apply && GetSpellProto()->Id == 58875)          // Spirit Walk
        target->CastSpell(target, 58876, true);

    target->UpdateSpeed(MOVE_RUN, true);

    if (apply)
    {
        switch (GetId())
        {
        case 68992:          // Darkflight, worgen's sprint spell.
        {
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->setInWorgenForm(UNIT_FLAG2_WORGEN_TRANSFORM2);
            break;
        }
        default:
            break;
        }
    }
}

void AuraEffect::HandleAuraModIncreaseMountedSpeed (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    HandleAuraModIncreaseSpeed(aurApp, mode, apply);
}

void AuraEffect::HandleAuraModIncreaseFlightSpeed (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    // Enable Fly mode for flying mounts
    if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK && (apply || (!target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !target->HasAuraType(SPELL_AURA_FLY))))
        {
            if (Player *plr = target->m_movedPlayer)
            {
                WorldPacket data;
                if (apply)
                    data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12, true);
                else
                    data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12, true);
                data.append(plr->GetPackGUID());
                data << uint32(0);          // unknown
                plr->SendDirectMessage(&data);
            }
        }

        if (mode & AURA_EFFECT_HANDLE_REAL)
        {
            //Players on flying mounts must be immune to polymorph
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);

            // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
            if (apply && target->HasAuraEffect(42016, 0) && target->GetMountID())
                target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 16314);
        }
    }

    if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
        target->UpdateSpeed(MOVE_FLIGHT, true);
}

void AuraEffect::HandleAuraModIncreaseSwimSpeed (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    target->UpdateSpeed(MOVE_SWIM, true);
}

void AuraEffect::HandleAuraModDecreaseSpeed (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    target->UpdateSpeed(MOVE_RUN, true);
    target->UpdateSpeed(MOVE_SWIM, true);
    target->UpdateSpeed(MOVE_FLIGHT, true);
    target->UpdateSpeed(MOVE_RUN_BACK, true);
    target->UpdateSpeed(MOVE_SWIM_BACK, true);
    target->UpdateSpeed(MOVE_FLIGHT_BACK, true);
}

void AuraEffect::HandleAuraModUseNormalSpeed (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->UpdateSpeed(MOVE_RUN, true);
    target->UpdateSpeed(MOVE_SWIM, true);
    target->UpdateSpeed(MOVE_FLIGHT, true);
}

/*********************************************************/
/***                     IMMUNITY                      ***/
/*********************************************************/

void AuraEffect::HandleModStateImmunityMask (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    std::list<AuraType> immunity_list;
    if (GetMiscValue() & (1 << 10))
        immunity_list.push_back(SPELL_AURA_MOD_STUN);
    if (GetMiscValue() & (1 << 1))
        immunity_list.push_back(SPELL_AURA_TRANSFORM);

    // These flag can be recognized wrong:
    if (GetMiscValue() & (1 << 6))
        immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
    if (GetMiscValue() & (1 << 0))
        immunity_list.push_back(SPELL_AURA_MOD_ROOT);
    if (GetMiscValue() & (1 << 2))
        immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
    if (GetMiscValue() & (1 << 9))
        immunity_list.push_back(SPELL_AURA_MOD_FEAR);

    // must be last due to Bladestorm
    if (GetMiscValue() & (1 << 7))
        immunity_list.push_back(SPELL_AURA_MOD_DISARM);

    // TODO: figure out a better place to put this...
    // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated.
    // however not all mechanic specified in immunity
    if (GetId() == 46924)
    {
        immunity_list.pop_back();          // delete Disarm
        immunity_list.push_back(SPELL_AURA_MOD_PACIFY_SILENCE);
        target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
        // Inmunidad a mind control y hex
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
    }

    if (apply && GetSpellProto()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
        for (std::list<AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter)
            target->RemoveAurasByType(*iter);

    for (std::list<AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter)
        target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply);
    // stop handling the effect if it was removed by linked event
    if (aurApp->GetRemoveMode())
        return;
}

void AuraEffect::HandleModMechanicImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();
    uint32 mechanic;

    switch (GetId())
    {
    case 42292:          // PvP trinket
    case 59752:          // Every Man for Himself
        mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
        // Actually we should apply immunities here, too, but the aura has only 100 ms duration, so there is practically no point
        break;
    case 54508:          // Demonic Empowerment
        mechanic = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
        break;
    case 34471:          // The Beast Within
    case 19574:          // Bestial Wrath
        mechanic = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
        break;
    default:
        if (GetMiscValue() < 1)
            return;
        mechanic = 1 << GetMiscValue();
        target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply);
        break;
    }

    if (apply && GetSpellProto()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
        target->RemoveAurasWithMechanic(mechanic, AURA_REMOVE_BY_DEFAULT, GetId());
}

void AuraEffect::HandleAuraModEffectImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    // when removing flag aura, handle flag drop
    if (!(apply) && target->GetTypeId() == TYPEID_PLAYER && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION))
    {
        if (target->GetTypeId() == TYPEID_PLAYER)
        {
            if (target->ToPlayer()->InBattleground())
            {
                if (Battleground *bg = target->ToPlayer()->GetBattleground())
                    bg->EventPlayerDroppedFlag(target->ToPlayer());
            }
            else
                sOutdoorPvPMgr->HandleDropFlag((Player*) target, GetSpellProto()->Id);
        }
    }
    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, GetMiscValue(), apply);
}

void AuraEffect::HandleAuraModStateImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply && (GetSpellProto()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
        target->RemoveAurasByType(AuraType(GetMiscValue()), NULL, GetBase());

    target->ApplySpellImmune(GetId(), IMMUNITY_STATE, GetMiscValue(), apply);
}

void AuraEffect::HandleAuraModSchoolImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL)
        target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);

    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    target->ApplySpellImmune(GetId(), IMMUNITY_SCHOOL, GetMiscValue(), (apply));

    // remove all flag auras (they are positive, but they must be removed when you are immune)
    if ((GetSpellProto()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) && (GetSpellProto()->AttributesEx2 & SPELL_ATTR2_DAMAGE_REDUCED_SHIELD))
        target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);

    // TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else
    // Only positive immunity removes auras
    if (apply && GetSpellProto()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY && IsPositiveSpell(GetId()))
    {
        uint32 school_mask = GetMiscValue();
        Unit::AuraApplicationMap& Auras = target->GetAppliedAuras();
        for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();)
        {
            SpellEntry const *spell = iter->second->GetBase()->GetSpellProto();
            if ((GetSpellSchoolMask(spell) & school_mask) && CanSpellDispelAura(GetSpellProto(), spell) && !iter->second->IsPositive() && spell->Id != GetId())
                target->RemoveAura(iter);
            else
                ++iter;
        }
    }

    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    if (GetSpellProto()->Mechanic == MECHANIC_BANISH)
    {
        if (apply)
            target->AddUnitState(UNIT_STAT_ISOLATED);
        else
        {
            bool banishFound = false;
            Unit::AuraEffectList const& banishAuras = target->GetAuraEffectsByType(GetAuraType());
            for (Unit::AuraEffectList::const_iterator i = banishAuras.begin(); i != banishAuras.end(); ++i)
                if ((*i)->GetSpellProto()->Mechanic == MECHANIC_BANISH)
                {
                    banishFound = true;
                    break;
                }
            if (!banishFound)
                target->ClearUnitState(UNIT_STAT_ISOLATED);
        }
    }
}

void AuraEffect::HandleAuraModDmgImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplySpellImmune(GetId(), IMMUNITY_DAMAGE, GetMiscValue(), apply);
}

void AuraEffect::HandleAuraModDispelImmunity (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplySpellDispelImmunity(m_spellProto, DispelType(GetMiscValue()), apply);
}

/*********************************************************/
/***                  MODIFY STATS                     ***/
/*********************************************************/

/********************************/
/***        RESISTANCE        ***/
/********************************/

void AuraEffect::HandleAuraModResistanceExclusive (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    int32 modAmount = GetAmount();

    for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
    {
        if (GetMiscValue() & int32(1 << x))
        {
            int32 amount = target->GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE, 1 << x, this);

            if (amount < modAmount)
            {
                target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(modAmount - amount), apply);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    target->ApplyResistanceBuffModsMod(SpellSchools(x), aurApp->IsPositive(), float(modAmount - amount), apply);
            }
        }
    }
}

void AuraEffect::HandleAuraModResistance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
    {
        if (GetMiscValue() & int32(1 << x))
        {
            target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
            if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
                target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, float(GetAmount()), apply);
        }
    }
}

void AuraEffect::HandleAuraModBaseResistancePCT (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // only players have base stats
    if (target->GetTypeId() != TYPEID_PLAYER)
    {
        //pets only have base armor
        if (target->ToCreature()->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
            target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply);
    }
    else
    {
        for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
            if (GetMiscValue() & int32(1 << x))
                target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply);
    }
}

void AuraEffect::HandleModResistancePercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
    {
        if (GetMiscValue() & int32(1 << i))
        {
            target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
            if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
            {
                target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float) GetAmount(), apply);
                target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float) GetAmount(), apply);
            }
        }
    }
}

void AuraEffect::HandleModBaseResistance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // only players have base stats
    if (target->GetTypeId() != TYPEID_PLAYER)
    {
        //only pets have base stats
        if (target->ToCreature()->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
            target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
    }
    else
    {
        for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
            if (GetMiscValue() & (1 << i))
                target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
    }
}

void AuraEffect::HandleModTargetResistance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage

    // show armor penetration
    if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
        target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE, GetAmount(), apply);

    // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
    if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL) == SPELL_SCHOOL_MASK_SPELL)
        target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, GetAmount(), apply);
}

/********************************/
/***           STAT           ***/
/********************************/

void AuraEffect::HandleAuraModStat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (GetMiscValue() < -2 || GetMiscValue() > 4)
    {
        sLog->outError("WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue());
        return;
    }
    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
    {
        // -1 or -2 is all stats (misc < -2 checked in function beginning)
        if (GetMiscValue() < 0 || GetMiscValue() == i)
        {
            target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
            if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
                target->ApplyStatBuffMod(Stats(i), (float) GetAmount(), apply);
        }
    }
}

void AuraEffect::HandleModPercentStat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (GetMiscValue() < -1 || GetMiscValue() > 4)
    {
        sLog->outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
        return;
    }

    // only players have base stats
    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
        if (GetMiscValue() == i || GetMiscValue() == -1)
            target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply);
}

void AuraEffect::HandleModSpellDamagePercentFromStat (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Magic damage modifiers implemented in Unit::SpellDamageBonus
    // This information for client side use only
    // Recalculate bonus
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleModSpellHealingPercentFromStat (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Recalculate bonus
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleModSpellDamagePercentFromAttackPower (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Magic damage modifiers implemented in Unit::SpellDamageBonus
    // This information for client side use only
    // Recalculate bonus
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleModSpellHealingPercentFromAttackPower (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Recalculate bonus
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleAuraModSpellPowerPercent (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Recalculate bonus
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleModHealingDone (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // implemented in Unit::SpellHealingBonus
    // this information is for client side only
    target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}

void AuraEffect::HandleModTotalPercentStat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (GetMiscValue() < -1 || GetMiscValue() > 4)
    {
        sLog->outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
        return;
    }


  int32 noModifyStat = NULL;
  int32 statToModify = GetMiscValue();
  bool increment = false;
  
  // Custom Cases
  switch (GetId())
  {
    // Mark of the Wild
    case 79060:
    case 79061:
    {
      statToModify = STAT_STRENGTH; 
      noModifyStat = STAT_SPIRIT;
      increment = true;
      break;
    }
    default:
      break;
    break;
  }

    //save current and max HP before applying aura
    uint32 curHPValue = target->GetHealth();
    uint32 maxHPValue = target->GetMaxHealth();

  for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) 
  {    
    if ((statToModify == i || statToModify == -1)  &&  (statToModify != noModifyStat))
    {
      target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
      if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
        target->ApplyStatPercentBuffMod(Stats(i), (float) GetAmount(), apply);

      //recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
      if ((statToModify == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & SPELL_ATTR0_UNK4)) 
	  {
        uint32 newHPValue = target->CountPctFromMaxHealth( int32(100.0f * curHPValue / maxHPValue));
        if (!newHPValue)
          newHPValue = 1;
        target->SetHealth(newHPValue);
      }
        }
    if (increment)
      statToModify++;
    }

}

void AuraEffect::HandleAuraModResistenceOfStatPercent (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    if (GetMiscValue() != SPELL_SCHOOL_MASK_NORMAL)
    {
        // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
        // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
        sLog->outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) does not work for non-armor type resistances!");
        return;
    }

    // Recalculate Armor
    target->UpdateArmor();
}

void AuraEffect::HandleAuraModExpertise (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ToPlayer()->UpdateExpertise(BASE_ATTACK);
    target->ToPlayer()->UpdateExpertise(OFF_ATTACK);
}

/********************************/
/***      HEAL & ENERGIZE     ***/
/********************************/
void AuraEffect::HandleModPowerRegen (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Update manaregen value
    if (GetMiscValue() == POWER_MANA)
        target->ToPlayer()->UpdateManaRegen();
    // other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate
}

void AuraEffect::HandleModPowerRegenPCT (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    HandleModPowerRegen(aurApp, mode, apply);
}

void AuraEffect::HandleModManaRegen (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    //Note: an increase in regen does NOT cause threat.
    target->ToPlayer()->UpdateManaRegen();
}

void AuraEffect::HandleAuraModIncreaseHealth (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
        target->ModifyHealth(GetAmount());
    }
    else
    {
        if (int32(target->GetHealth()) > GetAmount())
            target->ModifyHealth(-GetAmount());
        else
            target->SetHealth(1);
        target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
    }
}

void AuraEffect::HandleAuraModIncreaseMaxHealth (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    uint32 oldhealth = target->GetHealth();
    double healthPercentage = (double) oldhealth / (double) target->GetMaxHealth();

    target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);

    // refresh percentage
    if (oldhealth > 0)
    {
        uint32 newhealth = uint32(ceil((double) target->GetMaxHealth() * healthPercentage));
        if (newhealth == 0)
            newhealth = 1;

        target->SetHealth(newhealth);
    }
}

void AuraEffect::HandleAuraModIncreaseEnergy (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    Powers powerType = target->getPowerType();
    if (int32(powerType) != GetMiscValue())
        return;

    UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);

    // Special case with temporary increase max/current power (percent)
    if (GetId() == 64904)          // Hymn of Hope
    {
        if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
        {
            int32 change = target->GetPower(powerType) + (apply ? GetAmount() : -GetAmount());
            if (change < 0)
                change = 0;
            target->SetPower(powerType, change);
        }
    }

    // generic flat case
    target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModIncreaseEnergyPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    Powers powerType = target->getPowerType();
    if (int32(powerType) != GetMiscValue())
        return;

    UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);

    float amount = float(GetAmount());

    if (apply)
    {
        target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
        target->ModifyPowerPct(powerType, amount, apply);
    }
    else
    {
        target->ModifyPowerPct(powerType, amount, apply);
        target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
    }
}

void AuraEffect::HandleAuraModIncreaseHealthPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // Unit will keep hp% after MaxHealth being modified if unit is alive.
    float percent = target->GetHealthPct();
    target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
    if (target->isAlive())
        target->SetHealth(target->CountPctFromMaxHealth(int32(percent)));
}

void AuraEffect::HandleAuraIncreaseBaseHealthPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
}

/********************************/
/***          FIGHT           ***/
/********************************/

void AuraEffect::HandleAuraModParryPercent (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ToPlayer()->UpdateParryPercentage();
}

void AuraEffect::HandleAuraModDodgePercent (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ToPlayer()->UpdateDodgePercentage();
}

void AuraEffect::HandleAuraModBlockPercent (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ToPlayer()->UpdateBlockPercentage();
}

void AuraEffect::HandleAuraModRegenInterrupt (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    HandleModManaRegen(aurApp, mode, apply);
}

void AuraEffect::HandleAuraModWeaponCritPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    for (int i = 0; i < MAX_ATTACK; ++i)
        if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
            target->ToPlayer()->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply);

    // mods must be applied base at equipped weapon class and subclass comparison
    // with spell->EquippedItemClass and  EquippedItemSubClassMask and EquippedItemInventoryTypeMask
    // GetMiscValue() comparison with item generated damage types

    if (GetSpellProto()->EquippedItemClass == -1)
    {
        target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
        target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
        target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
    }
}

void AuraEffect::HandleModHitChance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        target->ToPlayer()->UpdateMeleeHitChances();
        target->ToPlayer()->UpdateRangedHitChances();
    }
    else
    {
        target->m_modMeleeHitChance += (apply) ? GetAmount() : (-GetAmount());
        target->m_modRangedHitChance += (apply) ? GetAmount() : (-GetAmount());
    }
}

void AuraEffect::HandleModSpellHitChance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->UpdateSpellHitChances();
    else
        target->m_modSpellHitChance += (apply) ? GetAmount() : (-GetAmount());
}

void AuraEffect::HandleModSpellCritChance (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->UpdateAllSpellCritChances();
    else
        target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
}

void AuraEffect::HandleModSpellCritChanceShool (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    for (int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
        if (GetMiscValue() & (1 << school))
            target->ToPlayer()->UpdateSpellCritChance(school);
}

void AuraEffect::HandleAuraModCritPct (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
    {
        target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
        return;
    }

    target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
    target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
    target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);

    // included in Player::UpdateSpellCritChance calculation
    target->ToPlayer()->UpdateAllSpellCritChances();
}

/********************************/
/***         ATTACK SPEED     ***/
/********************************/

void AuraEffect::HandleModCastingSpeed (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyCastTimePercentMod((float) GetAmount(), apply);
}

void AuraEffect::HandleModMeleeRangedSpeedPct (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyAttackTimePercentMod(BASE_ATTACK, (float) GetAmount(), apply);
    target->ApplyAttackTimePercentMod(OFF_ATTACK, (float) GetAmount(), apply);
    target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float) GetAmount(), apply);
}

void AuraEffect::HandleModCombatSpeedPct (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyCastTimePercentMod(float(m_amount), apply);
    target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
    target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
    target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply);
}

void AuraEffect::HandleModAttackSpeed (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyAttackTimePercentMod(BASE_ATTACK, (float) GetAmount(), apply);
    target->UpdateDamagePhysical(BASE_ATTACK);
}

void AuraEffect::HandleModMeleeSpeedPct (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyAttackTimePercentMod(BASE_ATTACK, (float) GetAmount(), apply);
    target->ApplyAttackTimePercentMod(OFF_ATTACK, (float) GetAmount(), apply);
}

void AuraEffect::HandleAuraModRangedHaste (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float) GetAmount(), apply);
}

void AuraEffect::HandleRangedAmmoHaste (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float) GetAmount(), apply);
}

/********************************/
/***       COMBAT RATING      ***/
/********************************/

void AuraEffect::HandleModRating (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
        if (GetMiscValue() & (1 << rating))
            target->ToPlayer()->ApplyRatingMod(CombatRating(rating), GetAmount(), apply);
}

void AuraEffect::HandleModRatingFromStat (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // Just recalculate ratings
    for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
        if (GetMiscValue() & (1 << rating))
            target->ToPlayer()->ApplyRatingMod(CombatRating(rating), 0, apply);
}

/********************************/
/***        ATTACK POWER      ***/
/********************************/

void AuraEffect::HandleAuraModAttackPower (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if (float(GetAmount()) > 0.f)
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_POS, TOTAL_VALUE, float(GetAmount()), apply);
    else
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_NEG, TOTAL_VALUE, -float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModRangedAttackPower (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
        return;

    if (float(GetAmount()) > 0.f)
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED_POS, TOTAL_VALUE, float(GetAmount()), apply);
    else
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED_NEG, TOTAL_VALUE, -float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModAttackPowerPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
    if (float(GetAmount()) > 0.f)
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_POS, TOTAL_PCT, float(GetAmount()), apply);
    else
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_NEG, TOTAL_PCT, -float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModRangedAttackPowerPercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
        return;

    //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
    if (float(GetAmount()) > 0.f)
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED_POS, TOTAL_PCT, float(GetAmount()), apply);
    else
        target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED_NEG, TOTAL_PCT, -float(GetAmount()), apply);
}

void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // Recalculate bonus
    if (target->GetTypeId() == TYPEID_PLAYER && !(target->getClassMask() & CLASSMASK_WAND_USERS))
        target->ToPlayer()->UpdateAttackPowerAndDamage(true);
}

void AuraEffect::HandleAuraModAttackPowerOfStatPercent (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    HandleAuraModAttackPowerOfArmor(aurApp, mode, apply);
}

void AuraEffect::HandleAuraModAttackPowerOfArmor (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // Recalculate bonus
    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
/********************************/
/***        DAMAGE BONUS      ***/
/********************************/
void AuraEffect::HandleModDamageDone (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    // apply item specific bonuses for already equipped weapon
    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        for (int i = 0; i < MAX_ATTACK; ++i)
            if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
                target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
    }

    // GetMiscValue() is bitmask of spell schools
    // 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
    // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
    // 127 - full bitmask any damages
    //
    // mods must be applied base at equipped weapon class and subclass comparison
    // with spell->EquippedItemClass and  EquippedItemSubClassMask and EquippedItemInventoryTypeMask
    // GetMiscValue() comparison with item generated damage types

    if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
    {
        // apply generic physical damage bonuses including wand case
        if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
        {
            target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
            target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
            target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);

            if (target->GetTypeId() == TYPEID_PLAYER)
            {
                if (GetAmount() > 0)
                    target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, GetAmount(), apply);
                else
                    target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, -GetAmount(), apply);
            }
        }
    }

    // Skip non magic case for speedup
    if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0)
        return;

    if (GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0)
    {
        // wand magic case (skip generic to all item spell bonuses)
        // done in Player::_ApplyWeaponDependentAuraMods

        // Skip item specific requirements for not wand magic damage
        return;
    }

    // Magic damage modifiers implemented in Unit::SpellDamageBonus
    // This information for client side use only
    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        if (GetAmount() > 0)
        {
            for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
            {
                if ((GetMiscValue() & (1 << i)) != 0)
                    target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, GetAmount(), apply);
            }
        }
        else
        {
            for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
            {
                if ((GetMiscValue() & (1 << i)) != 0)
                    target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, -GetAmount(), apply);
            }
        }
        if (Guardian* pet = target->ToPlayer()->GetGuardianPet())
            pet->UpdateAttackPowerAndDamage();
    }
}

void AuraEffect::HandleModDamagePercentDone (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AURA MOD DAMAGE type:%u negative:%u", GetMiscValue(), GetAmount() > 0);

    // apply item specific bonuses for already equipped weapon
    if (target->GetTypeId() == TYPEID_PLAYER)
    {
        for (int i = 0; i < MAX_ATTACK; ++i)
            if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
                target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
    }

    // GetMiscValue() is bitmask of spell schools
    // 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
    // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
    // 127 - full bitmask any damages
    //
    // mods must be applied base at equipped weapon class and subclass comparison
    // with spell->EquippedItemClass and  EquippedItemSubClassMask and EquippedItemInventoryTypeMask
    // GetMiscValue() comparison with item generated damage types

    if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
    {
        // apply generic physical damage bonuses including wand case
        if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
        {
            target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
            target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
            target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
            // For show in client
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, GetAmount() / 100.0f, apply);
        }
    }

    // Skip non magic case for speedup
    if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0)
        return;

    if (GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0)
    {
        // wand magic case (skip generic to all item spell bonuses)
        // done in Player::_ApplyWeaponDependentAuraMods

        // Skip item specific requirements for not wand magic damage
        return;
    }

    // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
    // Send info to client
    if (target->GetTypeId() == TYPEID_PLAYER)
        for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
            target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, GetAmount() / 100.0f, apply);

    if (GetSpellProto()->Id == 84963)          //Inquisition
    {
        switch (GetBase()->GetUnitOwner()->GetPower(POWER_HOLY_POWER))
        {
        case 0:          // 1HP
            GetBase()->SetDuration(4000, true);
            break;
        case 1:          // 2HP
            GetBase()->SetDuration(8000, true);
            break;
        case 2:          // 3HP
            GetBase()->SetDuration(12000, true);
            break;
        }
    }
}

void AuraEffect::HandleModOffhandDamagePercent (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
}

void AuraEffect::HandleShieldBlockValue (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

    Unit *target = aurApp->GetTarget();

    BaseModType modType = FLAT_MOD;
    if (GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
        modType = PCT_MOD;

    if (target->GetTypeId() == TYPEID_PLAYER)
        target->ToPlayer()->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply);
}

/********************************/
/***        POWER COST        ***/
/********************************/

void AuraEffect::HandleModPowerCostPCT (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    float amount = GetAmount() / 100.0f;
    for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
        if (GetMiscValue() & (1 << i))
            target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + i, amount, apply);
}

void AuraEffect::HandleModPowerCost (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
        if (GetMiscValue() & (1 << i))
            target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + i, GetAmount(), apply);
}

void AuraEffect::HandleArenaPreparation (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
        target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
    else
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
        target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
    }
}

void AuraEffect::HandleNoReagentUseAura (AuraApplication const *aurApp, uint8 mode, bool /*apply*/) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    flag96 mask;
    Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE);
    for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
        mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex];

    target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1, mask[0]);
    target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 + 1, mask[1]);
    target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 + 2, mask[2]);
}

void AuraEffect::HandleAuraRetainComboPoints (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
    // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
    if (!(apply) && GetBase()->GetDuration() == 0 && target->ToPlayer()->GetComboTarget())
        if (Unit* unit = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
            target->ToPlayer()->AddComboPoints(unit, -GetAmount());
}

/*********************************************************/
/***                    OTHERS                         ***/
/*********************************************************/

void AuraEffect::HandleAuraDummy (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    Unit *caster = GetCaster();

    if (mode & AURA_EFFECT_HANDLE_REAL)
    {
        // AT APPLY
        if (apply)
        {
            // Overpower
            if (caster && m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[0] & 0x4)
            {
                // In addition, if you strike a player..
                if (target->GetTypeId() != TYPEID_PLAYER)
                    return;
                //  ..while they are casting
                if (target->IsNonMeleeSpellCasted(false, false, true, false, false))
                    if (AuraEffect * aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARRIOR, 2775, 0))
                        switch (aurEff->GetId())
                        {
                        // Unrelenting Assault, rank 1
                        case 46859:
                            target->CastSpell(target, 64849, true, NULL, aurEff);
                            break;
                            // Unrelenting Assault, rank 2
                        case 46860:
                            target->CastSpell(target, 64850, true, NULL, aurEff);
                            break;
                        }
            }
            switch (GetId())
            {
            case 1515:          // Tame beast
                // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
                if (caster && target->CanHaveThreatList())
                    target->AddThreat(caster, 10.0f);
                break;
            case 13139:          // net-o-matic
                // root to self part of (root_target->charge->root_self sequence
                if (caster)
                    caster->CastSpell(caster, 13138, true, NULL, this);
                break;
                // Guardian of Ancient Kings - Retribution
            case 86698:
            {
                caster->CastSpell(caster, 86701, true);
                break;
            }
                // Guardian of Ancient Kings - Holy
            case 86669:
            {
                caster->CastSpell(caster, 86674, true);
                break;
            }
                // Sudden Death Cataclysm Proc
            case 52437:
            {
                if (caster && caster->ToPlayer()->HasSpellCooldown(86346))
                    caster->ToPlayer()->RemoveSpellCooldown(86346, true);
                break;
            }
            case 37096:          // Blood Elf Illusion
            {
                if (caster)
                {
                    switch (caster->getGender())
                    {
                    case GENDER_FEMALE:
                        caster->CastSpell(target, 37095, true, NULL, this);          // Blood Elf Disguise
                        break;
                    case GENDER_MALE:
                        caster->CastSpell(target, 37093, true, NULL, this);
                        break;
                    default:
                        break;
                    }
                }
                break;
            }
            case 55198:          // Tidal Force
            {
                target->CastSpell(target, 55166, true, NULL, this);
                // set 3 stacks and 3 charges (to make all auras not disappear at once)
                Aura *owner_aura = target->GetAura(55166, GetCasterGUID());
                if (owner_aura)
                {
                    // This aura lasts 2 sec, need this hack to properly proc spells
                    // TODO: drop aura charges for ApplySpellMod in ProcDamageAndSpell
                    GetBase()->SetDuration(owner_aura->GetDuration());
                    // Make aura be not charged-this prevents removing charge on not crit spells
                    owner_aura->SetCharges(0);
                    owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount);
                }
                break;
            }
            case 33763:
                if (target->HasAura(92363, GetCasterGUID()))          // Get talent Malfurion's gift rank 1
                    if (roll_chance_i(2))          // Procs only 2% of the time
                        target->CastSpell(caster, 16870, true, NULL, this);          // Clearcasting
                if (target->HasAura(92364, GetCasterGUID()))          // Get talent Malfurion's gift rank 2
                    if (roll_chance_i(4))          // Procs only 4% of the time
                        target->CastSpell(caster, 16870, true, NULL, this);          // Clearcasting
                break;
            case 39850:          // Rocket Blast
                if (roll_chance_i(20))          // backfire stun
                    target->CastSpell(target, 51581, true, NULL, this);
                break;
            case 43873:          // Headless Horseman Laugh
                target->PlayDistanceSound(11965);
                break;
            case 46354:          // Blood Elf Illusion
                if (caster)
                {
                    switch (caster->getGender())
                    {
                    case GENDER_FEMALE:
                        caster->CastSpell(target, 46356, true, NULL, this);
                        break;
                    case GENDER_MALE:
                        caster->CastSpell(target, 46355, true, NULL, this);
                        break;
                    }
                }
                break;
            case 46361:          // Reinforced Net
                if (caster)
                {
                    float currentGroundLevel = target->GetBaseMap()->GetHeight(target->GetPositionX(), target->GetPositionY(), MAX_HEIGHT);
                    if (target->GetPositionZ() > currentGroundLevel)
                        target->GetMotionMaster()->MoveFall(currentGroundLevel);
                }
                break;
            case 46699:          // Requires No Ammo
                if (target->GetTypeId() == TYPEID_PLAYER)
                    target->ToPlayer()->RemoveAmmo();          // not use ammo and not allow use
                break;
            case 28832:          // Mark of Korth'azz
            case 28833:          // Mark of Blaumeux
            case 28834:          // Mark of Rivendare
            case 28835:          // Mark of Zeliek
                if (caster)          // actually we can also use cast(this, originalcasterguid)
                {
                    int32 damage;
                    switch (GetBase()->GetStackAmount())
                    {
                    case 1:
                        damage = 0;
                        break;
                    case 2:
                        damage = 500;
                        break;
                    case 3:
                        damage = 1000;
                        break;
                    case 4:
                        damage = 1500;
                        break;
                    case 5:
                        damage = 4000;
                        break;
                    case 6:
                        damage = 12000;
                        break;
                    default:
                        damage = 20000 + 1000 * (GetBase()->GetStackAmount() - 7);
                        break;
                    }
                    if (damage)
                        caster->CastCustomSpell(28836, SPELLVALUE_BASE_POINT0, damage, target);
                }
                break;
            case 63322:          // Saronite Vapors
            {
                int32 mana = int32(GetAmount() * pow(2.0f, GetBase()->GetStackAmount()));          // mana restore - bp * 2^stackamount
                int32 damage = mana * 2;          // damage

                caster->CastCustomSpell(target, 63337, &mana, NULL, NULL, true);
                caster->CastCustomSpell(target, 63338, &damage, NULL, NULL, true);
                break;
            }
            case 71563:
            {
                if (Aura* newAura = target->AddAura(71564, target))
                    newAura->SetStackAmount(newAura->GetSpellProto()->StackAmount);
                break;
            }
            case 73667:          // Stardust No. 2
            {
                caster->ToPlayer()->KilledMonsterCredit(39237, NULL);
                break;
            }
            case 74401:
            {
                caster->CastSpell(caster, GetAmount(), true);
                break;
            }
            case 91565:          // Faerie Fire
            {
                if (!caster || (mode & AURA_EFFECT_HANDLE_REAPPLY))
                    break;

                uint8 stackAmount = 0;

                if (caster->HasAura(16858))          // Feral Aggression
                    stackAmount = 2;
                if (caster->HasAura(16859))
                    stackAmount = 3;

                if (stackAmount)
                    GetBase()->SetStackAmount(stackAmount);

                break;
            }
            }
        }
        // AT REMOVE
        else
        {
            if ((IsQuestTameSpell(GetId())) && caster && caster->isAlive() && target->isAlive())
            {
                uint32 finalSpelId = 0;
                switch (GetId())
                {
                case 19548:
                    finalSpelId = 19597;
                    break;
                case 19674:
                    finalSpelId = 19677;
                    break;
                case 19687:
                    finalSpelId = 19676;
                    break;
                case 19688:
                    finalSpelId = 19678;
                    break;
                case 19689:
                    finalSpelId = 19679;
                    break;
                case 19692:
                    finalSpelId = 19680;
                    break;
                case 19693:
                    finalSpelId = 19684;
                    break;
                case 19694:
                    finalSpelId = 19681;
                    break;
                case 19696:
                    finalSpelId = 19682;
                    break;
                case 19697:
                    finalSpelId = 19683;
                    break;
                case 19699:
                    finalSpelId = 19685;
                    break;
                case 19700:
                    finalSpelId = 19686;
                    break;
                case 30646:
                    finalSpelId = 30647;
                    break;
                case 30653:
                    finalSpelId = 30648;
                    break;
                case 30654:
                    finalSpelId = 30652;
                    break;
                case 30099:
                    finalSpelId = 30100;
                    break;
                case 30102:
                    finalSpelId = 30103;
                    break;
                case 30105:
                    finalSpelId = 30104;
                    break;
                }

                if (finalSpelId)
                    caster->CastSpell(target, finalSpelId, true, NULL, this);
            }

            switch (m_spellProto->SpellFamilyName)
            {
            case SPELLFAMILY_GENERIC:
                switch (GetId())
                {
                case 2584:          // Waiting to Resurrect
                    // Waiting to resurrect spell cancel, we must remove player from resurrect queue
                    if (target->GetTypeId() == TYPEID_PLAYER)
                        if (Battleground *bg = target->ToPlayer()->GetBattleground())
                            bg->RemovePlayerFromResurrectQueue(target->GetGUID());
                    break;
                case 36730:          // Flame Strike
                {
                    target->CastSpell(target, 36731, true, NULL, this);
                    break;
                }
                case 44191:          // Flame Strike
                {
                    if (target->GetMap()->IsDungeon())
                    {
                        uint32 spellId = target->GetMap()->IsHeroic() ? 46163 : 44190;

                        target->CastSpell(target, spellId, true, NULL, this);
                    }
                    break;
                }
                case 42783:          // Wrath of the Astromancer
                    target->CastSpell(target, GetAmount(), true, NULL, this);
                    break;
                case 46308:          // Burning Winds casted only at creatures at spawn
                    target->CastSpell(target, 47287, true, NULL, this);
                    break;
                case 52172:          // Coyote Spirit Despawn Aura
                case 60244:          // Blood Parrot Despawn Aura
                    target->CastSpell((Unit*) NULL, GetAmount(), true, NULL, this);
                    break;
                case 58600:          // Restricted Flight Area
                    if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
                    {
                        target->CastSpell(target, 61286, true);
                        target->CastSpell(target, 58601, true);
                    }
                case 58730:          // Restricted Flight Area
                    if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
                    {
                        target->CastSpell(target, 58601, true);
                        target->CastSpell(target, 45472, true);
                    }
                    break;
                }
                break;
            case SPELLFAMILY_MAGE:
                // Living Bomb
                if (m_spellProto->SpellFamilyFlags[1] & 0x20000)
                {
                    AuraRemoveMode mode = aurApp->GetRemoveMode();
                    if (caster && (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE))
                        caster->CastSpell(target, GetAmount(), true);
                }
                break;
            case SPELLFAMILY_ROGUE:
                switch (GetId())
                {
                case 59628:          // Tricks of the Trade
                    target->SetReducedThreatPercent(0, 0);
                    break;
                case 57934:          // Tricks of the Trade
                    if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE || !caster->GetMisdirectionTarget())
                        target->SetReducedThreatPercent(0, 0);
                    else
                        target->SetReducedThreatPercent(0, caster->GetMisdirectionTarget()->GetGUID());
                    break;
                }
                break;
            case SPELLFAMILY_WARLOCK:
            {
                // Shadowburn
                if (GetId() == 29341)
                {
                    if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target) && !target->isAlive())
                        caster->CastSpell(target, 95810, true);
                }
                // Haunt
                if (m_spellProto->SpellFamilyFlags[1] & 0x40000)
                {
                    if (caster)
                        target->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this, GetCasterGUID());
                }
                break;
            }
            case SPELLFAMILY_DRUID:
                // Lifebloom
                if (GetSpellProto()->SpellFamilyFlags[1] & 0x10)
                {
                    // Final heal only on dispelled or duration end
                    if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && aurApp->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
                        return;

                    // final heal
                    int32 stack = GetBase()->GetStackAmount();
                    target->CastCustomSpell(target, 33778, &m_amount, &stack, NULL, true, NULL, this, GetCasterGUID());
                }
                break;
            case SPELLFAMILY_PRIEST:
                // Vampiric Touch
                if (m_spellProto->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && GetEffIndex() == 0)
                {
                    // Dispel Damage
                    if (AuraEffect const * aurEff = GetBase()->GetEffect(1))
                    {
                        int32 damage = aurEff->GetAmount() * 8;
                        target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL, GetCasterGUID());
                    }

                    // Sin and Punishment
                    if (AuraEffect* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 1869, 1))
                    {
                        int32 chance = 0;
                        if (aurEff->GetSpellProto()->Id == 87099)
                            chance = 50;
                        if (aurEff->GetSpellProto()->Id == 87100)
                            chance = 100;
                        if (roll_chance_i(chance))
                            target->CastCustomSpell(target, 87204, NULL, NULL, NULL, true, NULL, NULL, GetCasterGUID());
                    }
                }
                break;
            case SPELLFAMILY_HUNTER:
                switch (GetId())
                {
                case 35079:          // Misdirection
                    target->SetReducedThreatPercent(0, 0);
                    break;
                case 34477:          // Misdirection
                    if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT)
                        target->SetReducedThreatPercent(0, 0);
                    break;
                }
            case SPELLFAMILY_DEATHKNIGHT:
                // Summon Gargoyle (Dismiss Gargoyle at remove)
                if (GetId() == 61777)
                    target->CastSpell(target, GetAmount(), true);
                break;
            case SPELLFAMILY_PALADIN:
            {
                switch (GetId())
                {
                // Guardian of Ancient Kings - Retribution
                case 86698:
                {
                    if (aurApp->GetBase()->GetOwner()->ToUnit()->HasAura(86700))
                    {
                        caster->CastSpell((Unit*) NULL, 86704, true);
                        caster->RemoveAura(86701);
                        caster->RemoveAura(86700);
                    }
                    break;
                }
                }
            }
            }
        }
    }

    // AT APPLY & REMOVE

    switch (m_spellProto->SpellFamilyName)
    {
    case SPELLFAMILY_GENERIC:
    {
        if (!(mode & AURA_EFFECT_HANDLE_REAL))
            break;
        switch (GetId())
        {
        // Recently Bandaged
        case 11196:
            target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply);
            break;
            // Unstable Power
        case 24658:
        {
            uint32 spellId = 24659;
            if (apply && caster)
            {
                SpellEntry const * spell = sSpellStore.LookupEntry(spellId);

                for (uint32 i = 0; i < spell->StackAmount; ++i)
                    caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
                break;
            }
            target->RemoveAurasDueToSpell(spellId);
            break;
        }
            // Restless Strength
        case 24661:
        {
            uint32 spellId = 24662;
            if (apply && caster)
            {
                SpellEntry const * spell = sSpellStore.LookupEntry(spellId);
                for (uint32 i = 0; i < spell->StackAmount; ++i)
                    caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
                break;
            }
            target->RemoveAurasDueToSpell(spellId);
            break;
        }
            // Tag Murloc
        case 30877:
        {
            // Tag/untag Blacksilt Scout
            target->SetEntry(apply ? 17654 : 17326);
            break;
        }
            //Summon Fire Elemental
        case 40133:
        {
            if (!caster)
                break;

            Unit *owner = caster->GetOwner();
            if (owner && owner->GetTypeId() == TYPEID_PLAYER)
            {
                if (apply)
                    owner->CastSpell(owner, 8985, true);
                else
                    owner->ToPlayer()->RemovePet(NULL, PET_SLOT_OTHER_PET, true);
            }
            break;
        }
            //Summon Earth Elemental
        case 40132:
        {
            if (!caster)
                break;

            Unit *owner = caster->GetOwner();
            if (owner && owner->GetTypeId() == TYPEID_PLAYER)
            {
                if (apply)
                    owner->CastSpell(owner, 19704, true);
                else
                    owner->ToPlayer()->RemovePet(NULL, PET_SLOT_OTHER_PET, true);
            }
            break;
        }
        case 57723:          // Exhaustion
        case 57724:          // Sated
        case 80354:          // Temporal Displacement
        case 95809:          // Insanity
        {
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 32182, apply);          // Heroism
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 2825, apply);          // Bloodlust
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 80353, apply);          // Time Warp
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 90355, apply);          // Ancient Hysteria
            break;
        }
        case 57819:          // Argent Champion
        case 57820:          // Ebon Champion
        case 57821:          // Champion of the Kirin Tor
        case 57822:          // Wyrmrest Champion
        case 93337:          // Champion of Ramkahen
        case 93339:          // Champion of the Earthen Ring
        case 93341:          // Champion of the Guardians of Hyjal
        case 93347:          // Champion of Therazane
        case 93368:          // Champion of the Wildhammer Clan
        case 94158:          // Champion of the Dragonmaw Clan
        case 93795:          // Stormwind Champion
        case 93805:          // Ironforge Champion
        case 93806:          // Darnassus Champion
        case 93811:          // Exodar Champion
        case 93816:          // Gilneas Champion
        case 93821:          // Gnomeregan Champion
        case 93825:          // Orgrimmar Champion
        case 93827:          // Darkspear Champion
        case 93828:          // Silvermoon Champion
        case 93830:          // Bilgewater Champion
        case 94462:          // Undercity Champion
        case 94463:          // Thunder Bluff Champion
        {
            if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
                break;

            uint32 FactionID = 0;
            uint32 DungeonLevel = 0;

            if (apply)
            {
                switch (m_spellProto->Id)
                {
                // Wrath of the Lich King factions
                case 57819:
                    FactionID = 1106;
                    DungeonLevel = 80;
                    break;          // Argent Crusade
                case 57820:
                    FactionID = 1098;
                    DungeonLevel = 80;
                    break;          // Knights of the Ebon Blade
                case 57821:
                    FactionID = 1090;
                    DungeonLevel = 80;
                    break;          // Kirin Tor
                case 57822:
                    FactionID = 1091;
                    DungeonLevel = 80;
                    break;          // The Wyrmrest Accord
                    // Cataclysm factions
                case 93337:
                    FactionID = 1173;
                    DungeonLevel = 85;
                    break;          // Ramkahen
                case 93339:
                    FactionID = 1135;
                    DungeonLevel = 85;
                    break;          // The Earthen Ring
                case 93341:
                    FactionID = 1158;
                    DungeonLevel = 85;
                    break;          // Guardians of Hyjal
                case 93347:
                    FactionID = 1171;
                    DungeonLevel = 85;
                    break;          // Therazane
                case 93368:
                    FactionID = 1174;
                    DungeonLevel = 85;
                    break;          // Wildhammer Clan
                case 94158:
                    FactionID = 1172;
                    DungeonLevel = 85;
                    break;          // Dragonmaw Clan
                    // Alliance factions
                case 93795:
                    FactionID = 72;
                    DungeonLevel = 0;
                    break;          // Stormwind
                case 93805:
                    FactionID = 47;
                    DungeonLevel = 0;
                    break;          // Ironforge
                case 93806:
                    FactionID = 69;
                    DungeonLevel = 0;
                    break;          // Darnassus
                case 93811:
                    FactionID = 930;
                    DungeonLevel = 0;
                    break;          // Exodar
                case 93816:
                    FactionID = 1134;
                    DungeonLevel = 0;
                    break;          // Gilneas
                case 93821:
                    FactionID = 54;
                    DungeonLevel = 0;
                    break;          // Gnomeregan
                    // Horde factions
                case 93825:
                    FactionID = 76;
                    DungeonLevel = 0;
                    break;          // Orgrimmar
                case 93827:
                    FactionID = 530;
                    DungeonLevel = 0;
                    break;          // Darkspear Trolls
                case 93828:
                    FactionID = 911;
                    DungeonLevel = 0;
                    break;          // Silvermoon
                case 93830:
                    FactionID = 1133;
                    DungeonLevel = 0;
                    break;          // Bilgewater Cartel
                case 94462:
                    FactionID = 68;
                    DungeonLevel = 0;
                    break;          // Undercity
                case 94463:
                    FactionID = 81;
                    DungeonLevel = 0;
                    break;          // Thunder Bluff
                }
            }
            caster->ToPlayer()->SetChampioningFaction(FactionID, DungeonLevel);
            break;
        }
            // LK Intro VO (1)
        case 58204:
            if (target->GetTypeId() == TYPEID_PLAYER)
            {
                // Play part 1
                if (apply)
                    target->PlayDirectSound(14970, target->ToPlayer());
                // continue in 58205
                else
                    target->CastSpell(target, 58205, true);
            }
            break;
            // LK Intro VO (2)
        case 58205:
            if (target->GetTypeId() == TYPEID_PLAYER)
            {
                // Play part 2
                if (apply)
                    target->PlayDirectSound(14971, target->ToPlayer());
                // Play part 3
                else
                    target->PlayDirectSound(14972, target->ToPlayer());
            }
            break;

        case 87840:          //Rune wild
            if (target->GetTypeId() == TYPEID_PLAYER && target->HasAura(87840))
            {
                if (target->HasSpell(33391))          // Journeyman Riding
                    target->ToPlayer()->SetSpeed(MOVE_RUN, 2.0f, true);
                else if (target->HasSpell(33388))          // Apprentice Riding
                    target->ToPlayer()->SetSpeed(MOVE_RUN, 1.6f, true);
            }
            else
                target->ToPlayer()->SetSpeed(MOVE_RUN, 1.0f, true);
            target->ToPlayer()->setInWorgenForm(UNIT_FLAG2_WORGEN_TRANSFORM3);
            break;

        case 62061:          // Festive Holiday Mount
            if (target->HasAuraType(SPELL_AURA_MOUNTED))
            {
                uint32 creatureEntry = 0;
                if (apply)
                {
                    if (target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
                        creatureEntry = 24906;
                    else
                        creatureEntry = 15665;
                }
                else
                    creatureEntry = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue();

                if (CreatureInfo const* creatureInfo = ObjectMgr::GetCreatureTemplate(creatureEntry))
                {
                    uint32 team = 0;
                    if (target->GetTypeId() == TYPEID_PLAYER)
                        team = target->ToPlayer()->GetTeam();

                    uint32 display_id = sObjectMgr->ChooseDisplayId(team, creatureInfo);
                    CreatureModelInfo const *minfo = sObjectMgr->GetCreatureModelRandomGender(display_id);
                    if (minfo)
                        display_id = minfo->modelid;

                    target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, display_id);
                }
            }
            break;
        }

        break;
    }
    case SPELLFAMILY_MAGE:
        {
            //if (!(mode & AURA_EFFECT_HANDLE_REAL))
                //break;
            break;
        }
    case SPELLFAMILY_PRIEST:
        {
            // if (!(mode & AURA_EFFECT_HANDLE_REAL))
                // break;
            break;
        }
    case SPELLFAMILY_DRUID:
    {
        if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
            break;
        switch (GetId())
        {
        case 52610:          // Savage Roar
        {
            uint32 spellId = 62071;
            if (apply)
            {
                if (target->GetShapeshiftForm() != FORM_CAT)
                    break;

                target->CastSpell(target, spellId, true, NULL, NULL, GetCasterGUID());
                break;
            }
            target->RemoveAurasDueToSpell(spellId);
            break;
        }
        case 61336:          // Survival Instincts
        {
            if (!(mode & AURA_EFFECT_HANDLE_REAL))
                break;

            if (apply)
            {
                if (target->IsInFeralForm())
                    target->CastSpell(target, 50322, true);
            }
            else
                target->RemoveAurasDueToSpell(50322);
            break;
        }
        }
        // Predatory Strikes
        if (target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
            target->ToPlayer()->UpdateAttackPowerAndDamage();
        break;
    }
    case SPELLFAMILY_SHAMAN:
    {
        if (!(mode & AURA_EFFECT_HANDLE_REAL))
            break;
        // Sentry Totem
        if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
        {
            if (apply)
            {
                uint64 guid = caster->m_SummonSlot[3];
                if (guid)
                {
                    Creature *totem = caster->GetMap()->GetCreature(guid);
                    if (totem && totem->isTotem())
                        caster->ToPlayer()->CastSpell(totem, 6277, true);
                }
            }
            else
                caster->ToPlayer()->StopCastingBindSight();
            return;
        }
        break;
    }
    case SPELLFAMILY_PALADIN:
        switch (GetId())
        {
        case 25771:          //Forbearance
        {
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 1022, apply);          // Hand of Protection
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 642, apply);          // Divine Shield
            target->ApplySpellImmune(GetId(), IMMUNITY_ID, 633, apply);          // Lay on Hands
            break;
        }
        }
        break;
    case SPELLFAMILY_ROGUE:
    {
        switch (GetId())
        {
        // Smoke bomb
        case 76577:
        {
            if (apply)
            {
                if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(88611))
                {
                    if (Aura* aur = Aura::TryCreate(spellInfo, target, this->GetCaster()))
                    {
                        aur->SetMaxDuration(GetBase()->GetDuration());
                        aur->SetDuration(GetBase()->GetDuration());
                    }
                }
            }
            else
                target->RemoveAura(88611);
            break;
        }
        }
        break;
    }
    }

    // stop handling the effect if it was removed by linked event
    if (apply && aurApp->GetRemoveMode())
        return;

    if (mode & AURA_EFFECT_HANDLE_REAL)
    {
        // pet auras
        if (PetAura const *petSpell = sSpellMgr->GetPetAura(GetId(), m_effIndex))
        {
            if (apply)
                target->AddPetAura(petSpell);
            else
                target->RemovePetAura(petSpell);
        }
    }
}

void AuraEffect::HandleChannelDeathItem (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    if (!(apply))
    {
        Unit *caster = GetCaster();

        if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
            return;

        Player *plCaster = caster->ToPlayer();
        Unit *target = aurApp->GetTarget();

        if (target->getDeathState() != JUST_DIED)
            return;

        // Item amount
        if (GetAmount() <= 0)
            return;

        if (GetSpellProto()->EffectItemType[m_effIndex] == 0)
            return;

        //Adding items
        uint32 noSpaceForCount = 0;
        uint32 count = m_amount;

        ItemPosCountVec dest;
        uint8 msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellProto()->EffectItemType[m_effIndex], count, &noSpaceForCount);
        if (msg != EQUIP_ERR_OK)
        {
            count -= noSpaceForCount;
            plCaster->SendEquipError(msg, NULL, NULL, GetSpellProto()->EffectItemType[m_effIndex]);
            if (count == 0)
                return;
        }

        Item *newitem = plCaster->StoreNewItem(dest, GetSpellProto()->EffectItemType[m_effIndex], true);
        if (!newitem)
        {
            plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
            return;
        }
        plCaster->SendNewItem(newitem, count, true, true);
    }
}

void AuraEffect::HandleBindSight (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    Unit *caster = GetCaster();

    if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
        return;

    caster->ToPlayer()->SetViewpoint(target, (apply));
}

void AuraEffect::HandleForceReaction (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    Player *player = target->ToPlayer();

    uint32 faction_id = GetMiscValue();
    ReputationRank faction_rank = ReputationRank(m_amount);

    player->GetReputationMgr().ApplyForceReaction(faction_id, faction_rank, apply);
    player->GetReputationMgr().SendForceReactions();

    // stop fighting if at apply forced rank friendly or at remove real rank friendly
    if ((apply && faction_rank >= REP_FRIENDLY) || (!apply && player->GetReputationRank(faction_id) >= REP_FRIENDLY))
        player->StopAttackFaction(faction_id);
}

void AuraEffect::HandleAuraEmpathy (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_UNIT)
        return;

    if (!(apply))
    {
        // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
        if (target->HasAuraType(GetAuraType()))
            return;
    }

    CreatureInfo const * ci = ObjectMgr::GetCreatureTemplate(target->GetEntry());
    if (ci && ci->type == CREATURE_TYPE_BEAST)
        target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
}

void AuraEffect::HandleAuraModFaction (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        target->setFaction(GetMiscValue());
        if (target->GetTypeId() == TYPEID_PLAYER)
            target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
    }
    else
    {
        target->RestoreFaction();
        if (target->GetTypeId() == TYPEID_PLAYER)
            target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
    }
}

void AuraEffect::HandleComprehendLanguage (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
        target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
    else
    {
        if (target->HasAuraType(GetAuraType()))
            return;

        target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
    }
}

void AuraEffect::HandleAuraConvertRune (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    Player *plr = (Player*) target;

    if (plr->getClass() != CLASS_DEATH_KNIGHT)
        return;

    uint32 runes = m_amount;
    // convert number of runes specified in aura amount of rune type in miscvalue to runetype in miscvalueb
    if (apply)
    {
        for (uint32 i = 0; i < MAX_RUNES && runes; ++i)
        {
            if (GetMiscValue() != plr->GetCurrentRune(i))
                continue;
            if (!plr->GetRuneCooldown(i))
            {
                plr->AddRuneByAuraEffect(i, RuneType(GetMiscValueB()), this);
                --runes;
            }
        }
    }
    else
        plr->RemoveRunesByAuraEffect(this);
}

void AuraEffect::HandleAuraLinked (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (apply)
    {
        Unit * caster = GetTriggeredSpellCaster(m_spellProto, GetCaster(), target);

        if (!caster)
            return;
        // If amount avalible cast with basepoints (Crypt Fever for example)
        if (GetAmount())
            caster->CastCustomSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex], &m_amount, NULL, NULL, true, NULL, this);
        else
            caster->CastSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex], true, NULL, this);
    }
    else
        target->RemoveAura(m_spellProto->EffectTriggerSpell[m_effIndex], GetCasterGUID(), 0, AuraRemoveMode(aurApp->GetRemoveMode()));
}

void AuraEffect::HandleAuraOpenStable (AuraApplication const *aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit *target = aurApp->GetTarget();

    if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
        return;

    if (apply)
        target->ToPlayer()->GetSession()->SendStablePet(target->GetGUID());

    // client auto close stable dialog at !apply aura
}

void AuraEffect::HandleAuraOverrideSpells (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Player * target = aurApp->GetTarget()->ToPlayer();

    if (!target || !target->IsInWorld())
        return;

    uint32 overrideId = uint32(GetMiscValue());

    if (apply)
    {
        target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, overrideId);
        if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId))
            for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i)
                if (uint32 spellId = overrideSpells->spellId[i])
                    target->AddTemporarySpell(spellId);
    }
    else
    {
        target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, 0);
        if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId))
            for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i)
                if (uint32 spellId = overrideSpells->spellId[i])
                    target->RemoveTemporarySpell(spellId);
    }
}

void AuraEffect::HandleAuraModFakeInebriation (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit* target = aurApp->GetTarget();

    if (apply)
    {
        target->m_invisibilityDetect.AddFlag(INVISIBILITY_DRUNK);
        target->m_invisibilityDetect.AddValue(INVISIBILITY_DRUNK, GetAmount());

        if (target->GetTypeId() == TYPEID_PLAYER)
        {
            int32 oldval = target->ToPlayer()->GetInt32Value(PLAYER_FAKE_INEBRIATION);
            target->ToPlayer()->SetInt32Value(PLAYER_FAKE_INEBRIATION, oldval + GetAmount());
        }
    }
    else
    {
        bool removeDetect = !target->HasAuraType(SPELL_AURA_MOD_FAKE_INEBRIATE);

        target->m_invisibilityDetect.AddValue(INVISIBILITY_DRUNK, -GetAmount());

        if (target->GetTypeId() == TYPEID_PLAYER)
        {
            int32 oldval = target->ToPlayer()->GetInt32Value(PLAYER_FAKE_INEBRIATION);
            target->ToPlayer()->SetInt32Value(PLAYER_FAKE_INEBRIATION, oldval - GetAmount());

            if (removeDetect)
                removeDetect = !target->ToPlayer()->GetDrunkValue();
        }

        if (removeDetect)
            target->m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
    }

    target->UpdateObjectVisibility();
}

void AuraEffect::HandleAuraSetVehicle (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
    if (!(mode & AURA_EFFECT_HANDLE_REAL))
        return;

    Unit * target = aurApp->GetTarget();

    if (!target->IsInWorld())
        return;

    uint32 vehicleId = GetMiscValue();

    if (apply)
    {
        if (!target->CreateVehicleKit(vehicleId))
            return;
    }
    else if (target->GetVehicleKit())
        target->RemoveVehicleKit();

    if (target->GetTypeId() != TYPEID_PLAYER)
        return;

    WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, target->GetPackGUID().size() + 4);
    data.appendPackGUID(target->GetGUID());
    data << uint32(apply ? vehicleId : 0);
    target->SendMessageToSet(&data, true);

    if (apply)
    {
        data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
        target->ToPlayer()->GetSession()->SendPacket(&data);
    }
}
void AuraEffect::HandleAuraReplaceSpell (AuraApplication const * aurApp, uint8 mode, bool apply) const
{
       if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
        return;

   Player * target = aurApp->GetTarget()->ToPlayer();

    if (!target || !target->IsInWorld())
        return;

   uint32 overrideId = GetAmount();

    ActionBarSpellOverride const* spellOverride = sSpellMgr->GetActionBarSpellOverride(overrideId);

    if(!spellOverride)
        return;

    uint32 aura = spellOverride->aura;
    uint32 affSpell = spellOverride->affSpell;

    //Check Aura
    if(aura > 0 && !target->HasAura(aura))
        return;

    if (apply)
    {
        target->AddTemporarySpell(overrideId);
        WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
        data << uint32(affSpell);
        data << uint32(overrideId);
        target->GetSession()->SendPacket(&data);
    }
    else
    {
        target->RemoveTemporarySpell(overrideId);
        WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
        data << uint32(overrideId);
        data << uint32(affSpell);
        target->GetSession()->SendPacket(&data);
    }
}
